За последний год мы спроектировали (и продолжаем поддерживать) несколько IIoT проектов. Возможно, вы слышали о IIoT, но, на всякий случай, мы попробуем максимально просто объяснить что это такое и почему это интересно разработчикам, архитекторам и администраторам высоконагруженных решений.
IoT — интернет вещей — подразумевает управление устройствами, предназначенными для выполнения простых бытовых задач (открыть ворота гаража, когда подъезжает машина, включить свет по датчику движения или по команде, следить за температурой в помещении), то под IIoT — индустриальным интернетом вещей — обычно имеется в виду “оцифровка” данных с производств, на основе которых можно провести экспертный анализ, часто при помощи машинного обучения.
Например, можно собирать и анализировать данные с роторных моторов, чтобы вовремя узнавать о поломках и сэкономить на ремонте. Замена полностью сломанной турбины стоит сильно дороже, чем вовремя сделанный ремонт. Другой пример — добыча угля. Анализ данных о составе воздуха в шахтах позволяет вовремя реагировать на превышение допустимых значений. Это помогает предотвратить ситуации, создающие риск жизни для шахтеров.
Поток данных — от сенсоров на полях, от промышленных станков, от датчиков газа — поступает в агрегирующие хабы и, далее, в платформу обработки и анализа данных.
Мы хотим рассказать о том, как выглядит подобная архитектура, как можно достаточно просто собирать и анализировать данные, и остановимся на специфике отдельных приложений. Опираться будем на переводы англоязычных статей и собственный опыт проектирования. Эта статья — переводная, с нашими пояснениями и дополнениями.
В первой статье мы попробуем создать IIoT архитектуру, в которую в дальнейшем будем передавать данные от сенсоров, а следом передавать их в систему, которая обеспечивает обработку, анализ, машинное обучение и мониторинг поступающих данных.
Создаваемая архитектура
Часто в индустриальном IoT нет прямого доступа к датчикам и системам управления, поэтому для соединения уровней OT (операционных технологий) и IT (информационных технологий) используется шлюз.
Таким образом, IIoT архитектура обычно включает в себя: конечные устройства, шлюзы, региональные хабы и, наконец, системы обработки и хранения информации.
Создаваемая архитектура должна обеспечить возможность:
- Собирать данные с датчиков на шлюз
- Передавать данные в облако или датацентр
- Автоматически обновлять конфигурации шлюзов
- Поддерживать безопасную передачу и обработку большого объема данных
На изображении: архитектура создаваемой системы и ПО, которое мы будем использовать для ее построения на каждом уровне.
Датчики собирают данные и отсылают их на шлюз, используя самые разные проводные и беспроводные протоколы (Serial, RS-485, MODBUS, CAN bus, OPC UA, BLE, WiFi, и т.п.). В нашем примере мы будем иметь в виду, что данные приходят на шлюз по WiFi.
В качестве шлюза будем использовать Raspberry Pi, на котором будет запущен брокер Mosquitto и агент MiNiFi. Mosquitto — это опенсорсный, легковесный брокер сообщений, который мы будем использовать для дальнейшей передачи данных с датчиков по MQTT протоколу. MQTT добавляет минимальный оверхед и поэтому удобен для применения в IoT, когда аппаратные ресурсы конечных устройств ограничены (используются, например, телефоны и микроконтроллеры).
Apache MiNiFi — подпроект Apache NiFi — легковесный агент, который имплементирует основную функциональность Apache NiFi, специально предназначенного для сбора данных на конечных устройствах.
MiNiFi компактен, минимально использует ресурсы и позволяет централизованно управлять всеми агентами. Легко соединяется с NiFi с помощью Site-To-Site (S2S), что позволяет выстроить полноценное управление потоком данных — масштабируемое, безопасное и дающее ясное представление обо всех этапах передачи информации.
В нашей системе MiNiFi подпишется на все топики Mosquitto брокера и будет пересылать каждое сообщение в NiFi, установленный на региональном уровне. Также можно использовать его для соединения с системой SCADA или любым другим источником OT-данных.
На региональном уровне присутствуют два компонента:
Apache NiFi — это мощная система управления потоками данных, поддерживает более 200 коннекторов. Графический интерфейс позволяет быстро и просто проектировать потоки данных.
NiFi не жертвует мощностью ради простоты. Это хорошо масштабируемая распределенная система с гарантированной доставкой, backpressure (умением хранить данные до выгрузки их другими, более медленными системами) и балансировкой нагрузки. Эта функциональность делает NiFi отличным инструментом для IoT приложений, которые часто работают в условиях нестабильного сетевого окружения.
В нашей системе NiFi — это центр сбора данных, который перенаправляет их в различные системы и приложения (HDFS, HBase, Kafka, S3 итп).
MiNiFi C2 Server (MiNiFi Command & Control) это еще один подпроект Apache NiFi, который пока находится в разработке. Его роль — быть центральной точкой конфигурации сотен и тысяч MiNiFi агентов, находящихся в продакшене в полевых условиях (различные залы, заводы, территории). C2 сервер управляет конфигурациями потоков MiNiFi (в терминологии C2 — versioned class of applications) и публикует их через Rest API. MiNiFi агенты могут соединяться с этим API с заданной частотой для обновления собственной конфигурации.
Итак, давайте начнем создавать наш прототип.
Соглашение о именовании доменных имен
Для дальнейшей конфигурации различных систем, которые должны обращаться друг к другу давайте договоримся о названиях доменных имен, которые мы будем использовать в конфигурациях.
#сервер с Apache NiFi который занимается потоковой обработкой данных
192.168.0.20 nifi.iot.local
#сервер с Apache MiNiFi C2 который занимается распространением конфигураций MiNiFi
192.168.0.20 minifi-c2.iot.local
#raspberry pi, собирающий данные на производстве с Apache MiNiFi и MQTT брокером
192.168.0.68 iot-hub-1.iot.local
Подготовка Raspberry Pi: MQTT и MiNiFi
Чтобы установить брокер MQTT Mosquitto и агент MiNiFi запустите следующие команды на вашем Raspberry Pi.
По-умолчанию MiNiFi содержит минимальный набор обработчиков данных. Добавить дополнительные обработчики из комплекта NiFI можно, добавив NAR-архив (NiFi архив) в директорию с библиотеками.
Последней командой мы добавляем NAR MQTT обработчика.
sudo apt-get update
#install and run Mosquitto broker on default port 1883
sudo apt-get install mosquitto
mosquitto
#install and prepare MiNiFi agent
wget http://apache.crihan.fr/dist/nifi/minifi/0.4.0/minifi-0.4.0-bin.tar.gz
tar -xvf minifi-0.4.0-bin.tar.gz
cd minifi-0.4.0
#add mqtt processor
wget https://github.com/ahadjidj-hw/NiFi/raw/master/nifi-mqtt-nar-1.5.0.nar -P ./lib/
Теперь давайте установим сервер управлениями конфигураций MiNiFi C2 на сервер, который будет доступен с Raspberry Pi
Установка и конфигурирование MiNiFi C2 сервера.
Установите MiNiFi C2 сервер на публичный сервер, который будет доступен с MiNiFi агентов. Можно использовать иерархическое размещение серверов C2 для сложных сетевых инфраструктур, как описано чуть ниже. Запустите следующую команду чтобы установить C2 сервер:
wget http://apache.crihan.fr/dist/nifi/minifi/0.4.0/minifi-c2-0.4.0-bin.tar.gz
tar -xvf minifi-c2-0.4.0-bin.tar.gz
cd minifi-c2-0.4.0
- Сервер C2 будет публиковать конфигурацию, организованную по классам. C2 поддерживает подключаемые “провайдеры конфигурации”:
- The CacheConfigurationProvider, который обновляет конфигурации исходя из конфигурации заданной в файловой системы или на S3
- The DelegatingConfigurationProvider, который передает делегирование на другой C2 сервер для создания иерархических структур C2 серверов.
- The NiFiRestConfigurationProvider, который снимает шаблоны с серверов Apache NiFi через их REST API.
Настроим сервер C2, чтобы использовать NiFi как провайдера конфигурации. Отредактируйте файл ./conf/minifi-c2-context.xml, раскомментируйте xml-блок
<bean class="org.apache.nifi.minifi.c2.provider.nifi.rest.NiFiRestConfigurationProvider">
и пропишите адрес NiFi сервера (http://nifi.iot.local:8080 )
<constructor-arg>
<value>http://nifi.iot.local:8080/nifi-api</value>
</constructor-arg>
Дальнейшее конфигурирование MiNiFi на Raspberry Pi
По умолчанию, для добавления обработчиков и их конфигураций нужно отредактировать конфиг ./conf/config.yml. Конфигурацию также можно написать вручную или создать ее используя графический интерфейс Apache NiFi с последующим экспортом конфигурации в виде шаблона. Шаблон это XML-файл, который необходимо конвертировать в YML файл конфигурации MiNiFi, используя MiNiFi toolkit. Вот пример конфигурационного файла, который следит за файлом на устройстве и пересылает каждую новую строчку на NiFi, используя протокол S2S.
Для нашего проекта пользоваться ручной настройкой мы не будем. Ведь если MiNiFi-агентов будет много, то будет непросто вручную останавливать, редактировать config.yml и перезагружать агент каждый раз, когда конфигурация будет меняться.
MiNiFi использует Change Ingestor, с помощью которого агент узнает о новых возможных конфигурациях. Change Ingestor это подключаемый модуль, и есть три ChangeIngestor, которые штатно поддерживаются MiNiFi.
- FileChangeIngestor
- RestChangeIngestor
- PullHttpChangeIngestor
Мы будем использовать PullHttpChangeIngestor, чтобы периодически обращаться к серверу C2 и скачивать новую конфигурацию. Чтобы сконфигурировать этот Ingestor необходимо отредактировать файл ./conf/bootstrap.conf, раскомментировать соответствующие строки и установить следующие настройки:
nifi.minifi.notifier.ingestors=org.apache.nifi.minifi.bootstrap.configuration.ingestors.PullHttpChangeIngestor
# Hostname on which to pull configurations from
nifi.minifi.notifier.ingestors.pull.http.hostname=minifi-c2.iot.local
# Port on which to pull configurations from
nifi.minifi.notifier.ingestors.pull.http.port=10080
# Path to pull configurations from
nifi.minifi.notifier.ingestors.pull.http.path=/c2/config
# Query string to pull configurations with
nifi.minifi.notifier.ingestors.pull.http.query=class=iot-minifi-raspberry-agent
# Period on which to pull configurations from, defaults to 5 minutes if commented out
nifi.minifi.notifier.ingestors.pull.http.period.ms=60000
С такой конфигурацией каждый агент MiNiFi будет обращаться к серверу C2 по протоколу REST API по адресу http://minifi-c2.iot.local:10080/c2/config каждую минуту и запрашивать новую конфигурацию для класса iot-minifi-raspberry-agent
Важный момент: периодичность в 1 минуту выставлена только для демонстрации. В продакшен-среде, скорее всего, не придется обновлять агенты с такой частотой.
Прежде чем запускать агент, давайте переместимся на управляющий уровень и настроим MiNiFi C2 сервер и сам Apache NiFi.
Установка и конфигурирование NiFi сервера
Установите NiFi сервер, доступный с C2 сервера и запустите его.
wget http://apache.crihan.fr/dist/nifi/1.6.0/nifi-1.6.0-bin.tar.gz
tar -xvf nifi-1.6.0-bin.tar.gz
cd nifi-1.6.0
./bin/nifi.sh start
Соединитесь с NiFi интерфейсом по адресу http://nifi-dev:8080/nifi/ и создайте флоу, который будет запускаться на MiNiFi агентах, но перед этим добавьте Input Port (добавляется нажатием кнопки Input Port в меню) в корневом слое и назовите его from Raspberry MiNiFi. Это место, где NiFi будет получать файлы потоков от MiNiFi.
Добавьте Funnel и свяжите Input Port с Funnel — в дальнейших статьях мы коснемся обработки данных на стороне Apache NiFi.
Добавьте Processor consumeMQTT для подписки на Mosquitto брокер и подпишите его на все топики iot/sensors/* обратите внимание, что tcp://raspberrypi:1883 эквивалентно tcp://localhost:1883, так как этот поток будет запущен на Raspberry Pi
Используйте Processor UpdateAttribute чтобы добавить атрибут “version” который мы будем использовать для того, чтобы известить систему о переконфигурации. Вы можете добавлять любые дополнительные атрибуты: timestamp, location, имя агента и т.п.
И, наконец, добавьте Remote Process Group (RPG) — чтобы послать принятые события в NiFi. Соедините все эти три процесса.
Ваш поток теперь должен выглядеть как на скриншоте снизу. Левый поток будет запущен на самом Apache NiFi, и будет принимать данные с Apache MiNiFi. Правый поток поток не будет запускаться в рамках Apache Nifi, создан для целей прототипирования и конфигурации, и будет запускаться на Raspberry Pi.
Сохраните правый поток как шаблон с именем “iot-minifi-raspberry-agent.v1”. Принцип именования здесь чрезвычайно важен. Мы должны использовать то же имя, что и имя класса, используемое в конфигурации MiNiFi.
Очень важно — выделить нужно не только сохраняемые компоненты, но и связи между ними.
Размещение и запуск приложения
Перед запуском агентов MiNiFi на Raspberry Pi, давайте проверим, что C2 server правильно сконфигурирован. Откройте URL в вашем браузере: http://c2-server:10080/c2/config?class=iot-minifi-raspberry-agent&version=1 C2 Server должен ответить файлом, содержащим конфигурацию шаблона, который мы построили в YML формате.
Если вместо конфигурации сервер выдает Java Exception — вы столкнулись с проблемой в C2-сервере, упоминаемой здесь:
https://github.com/apache/nifi-minifi/pull/126#issuecomment-388856304
Нужно будет либо поставить версию 0.3.0, либо убрать файл javax.ws.rs-api-2.1.jar из папки lib директории C2-сервера.
Если вы посмотрите на логи C2 server, вы можете увидеть, что сервер принял запрос с параметрами {class=[iot-minifi-raspberry-agent], version=[1]}
Теперь, когда связь между отдельными компонентами архитектуры (MQTT, MiNiFi, NiFi и C2) установлена, запустите агента MiNiFi на Raspberry Pi с помощью команды:
./bin/minifi.sh start
Через несколько секунд вы должны увидеть логи C2 сервера. Хост 192.168.1.50 (в нашем случае это IP адрес устройства Raspberry Pi) запросил C2 сервер предоставить последнюю версию класса “iot-minifi-raspberry-agent”. В сравнении с предыдущим нашим запросом, который мы делали в браузере, вы можете обратить внимание, что MiNiFi не указал версию. Если вы откроете конфигурацию MiNiFi агента в ./conf/config.yml — вы увидите ту же конфигурацию, что мы получили в браузере, задав запрос руками.
MQTT показывает, что MiNiFi агент соединился с брокером и подписался на топики iot/sensors/#
Контроль передаваемых данных
Отлично, теперь давайте сделаем так, чтобы наши датчики начали генерировать данные и публиковать их в MQTT. MiNiFi начнет выгружать информацию и посылать в NiFi, как показано на скриншоте ниже.
Важно: Для того, чтобы компонент Apache NiFi начал работу надо нажать кнопку Play.
Теперь, давайте взглянем в одно из этих сообщений внутри NiFi. Информация идет от датчика “iot/sensors/LightIntensity/z”, версия приложения — 1
Обновление конфигурации MiNiFi
Теперь когда наша инфраструктура работает, а данные идут в наш “дата центр”, давайте задеплоим новую конфигурацию MiNiFi. Зайдите в интерфейс Apache NiFi и отредактируйте обработчик updateAttribute. Измените атрибут “version” на 2 вместо 1 и сохраните новый шаблон “iot-minifi-raspberry-agent.v2”. Вот и все. Новая конфигурация будет автоматически задеплоена.
Вы можете посмотреть на логи сервера C2 и увидеть что новая версия V2 была обнаружена, сервер не нашел ее в своем кэше и загрузил.
Затем MiNiFi обнаруживает новую конфигурацию, резервирует предыдущую конфигурацию выгружает новую и рестартует:
В следующей статье мы расскажем о том, как мы собрали датчики и включили их в нашу архитектуру. А после этого расскажем про анализ данных.
Автор: eapotapov