Предлагаем вашему вниманию проектную работу Артема Данильченко, выпускника курса «Highload Architect«.

Цель моей проектной работы — создать базовую архитектуру платформы для сбора, обработки и хранения данных от IoT-устройств. Данная платформа должна отвечать следующим требованиям:

  • поддержка различных протоколов транспортного уровня;
  • поддержка различного набора информационных протоколов сбора данных от устройств;
  • управление потоками данных внутри системы;
  • интеграции с внешними системами и API;
  • возможность создания Web-интерфейса для отображения данных.

Начало проектирования

Для снижения связности системы проектирование будет вестись с использованием подхода построения микросервисной архитектуры. Отличительными чертами данной архитектуры являются масштабируемость, адаптируемость и эволюционность.

Первый этап.  Цифровой портрет IoT-устройства

Будем считать, что наше «сферическое IoT-устройство в вакууме» будет установлено на беспилотном комбайне или тракторе (например фирмы «Ростсельмаш») и передает следующий набор параметров:

— свой уникальный идентификатор. Для простоты считаем, что идентификатор уникален и задается в прошивке устройства или при его первой инициализации/регистрации в сети;

— геокоординаты  и пространственные данные — широта и долгота, скорость и направление движения;

— системное время;

— техническое состояние устройства — заряд аккумулятор, уровень сигнала сети, уровень топлива, уровень масла, загруженность бункера, процент износа рабочих узлов и т. д.;

— счетчик переданных пакетов данных.

Особо стоит обратить внимание на то, что IoT-устройству придется работать в условиях плохого или нестабильного канала передачи данных. А это значит, что необходимо максимально сжимать пакет полезных данных для передачи и использовать различные информационные протоколы.

Второй Этап. Проектирование сервера сбора данных

Сервер сбора данных должен предоставлять следующие возможности:

  1. Поддержка TCP и UDP-протоколов транспортного уровня.
  2. Поддержка протоколов MQTT и LoRaWAN.
  3. Способность выдерживать несколько тысяч одновременных сетевых подключений.
  4. Быть экономичным в части потребления ресурсов.
  5. Скорость разработки и простота поддержки.

Для разработки такого сервера лучше всего подходят языки типа С, С++, Golang, Rust. Поскольку я несколько последних лет пишу исключительно на Golang, то для реализации MVP курсового проекта был выбран Golang.

Следующая проблема, которая возникает при реализации системы, — это источники данных. Не всегда есть под рукой нужные устройства или же их недостаточное количество. Выходом из такой ситуации является разработка своих программных имитаторов.

Программные имитаторы позволяют решить следующие проблемы:

  • сэкономить бюджет  проекта, не тратиться на закупку большого числа устройств;
  • создавать различные варианты нагрузки (плавное увеличение, DDOS, пиковая нагрузка);
  • упрощает поддержку и тестирование различных протоколов информационного обмена;
  • позволяет моделировать отказы и нештатные ситуации.

В курсовом проекте я сделал простую реализацию tcp сервера и имитатора клиента, которые производили обмен открытой ASCII-строкой со списком параметров.

###ID=1234235345&CNT=1&STM=220828003254&LAT=47.257178&LON=39.7633771***

Для имитации плохого канала связи между имитатором устройства и сервером был развернут  прокси «ToxyProxy» (https://github.com/Shopify/toxiproxy).

Применение этого инструмента позволяет смоделировать задержки в канале передачи данных,  timeout сервера, ограничение пропускной способности и т. д.

Итак, в качестве первого сегмента нашей системы мы можем нарисовать вот такую архитектурную схему:

Третий Этап. Накопление и передача данных для вторичной обработки

После приема данных сервером их необходимо передать на дальнейшую обработку. Но тут возникает ряд ограничений:

  • потребителями данных может быть не одна система;
  • данные поступают неравномерно и в пиковые моменты возможна задержка в обработке;
  • должна быть возможность маршрутизация трафика внутри системы.

На помощь приходит один из брокеров сообщений : ZeroMQ, RabbitMQ, NATS.

Для своего проекта я выбрал NATS ( https://docs.nats.io/ ). Мой выбор обоснован следующими доводами:

  • написан на Golang. Не требует дополнительных библиотек и фреймворков. Легко разворачивается на любой системе, даже без Docker;
  • поддержка механизмов Publish-Subscribe, Request-Reply, Streaming, Key/Value Store, MQTT;
  • простая маршрутизация сообщений;
  • у меня есть экспертиза по построению систем на базе NATS.

Как было сказано выше, брокер сообщений выступает связующим звеном для различных подсистем платформы:

  1. Подсистема обработки входяших сообщений IoT-устройств. В задачи данной системы входит распаковка входящих данных, сохранение их в БД и передача в другие системы для вторичной обработки. Реализация выполнена на Golang + PostgreSQL.
  2. Подсистема управления устройствами. Отвечает за управление настройками устройств, формирование и передачу новых настроек функционирования устройства (например — частота выхода на связь).
  3. Подсистема уведомлений. Отвечает за централизованную рассылку оповещений по изменению состояния или параметров устройств или объекта наблюдения.
  4. Подсистема геопозиционирования и картографии. Подсистема для взаимодействия с внешними системами картографии, геопозиционирования, топопривязки. OpenStreetMap, YandexMap, ArcGIS. Так как геоданные являются редкоизменяемыми с долгой актуальностью, для снижения нагрузки на внешние системы и увеличения скорости запросов можно поставить Reddis или аналоги для кэширования данных от внешних систем.

И теперь архитектура платформы принимает вот такой вид:

Создание архитектуры платформы для сбора, обработки и хранения данных от IoT-устройств

Четвертый этап. Web-интерфейс и внешнее API

Для реализации доступа к данным платформы предлагается сделать 2 API.

Создание архитектуры платформы для сбора, обработки и хранения данных от IoT-устройств

1. Public API. Программный интерфейс доступа для сторонних систем и сторонних разработчиков. Может быть реализован как обычный REST API с авторизацией доступа через jwt-token. Для защиты платформы от от ddos необходимо использовать rate limiter.

2. Internal API. Внутренний API используется для  обеспечения работы web-компонентов IoT-платформы. Например — мобильный клиент или личный кабинет с доступом через web-браузер. Оптимальным решением для организации работы будет использование gRPC с сериализацией данных через protobuf.

Данный подход позволит снизить объем трафика, обеспечить обратную совместимость и расширяемость API.

Любые запросы к серверу должны в обязательном порядке проходить через балансировщик нагрузки. По возможности, данные, которые запрашиваются из БД, должны кэшироваться.

В качестве простой реализации GUI я сделал вывод координат IoT-устройств  на карту. Для этого потребовалось написать простой web-сервер на go.

Создание архитектуры платформы для сбора, обработки и хранения данных от IoT-устройств

5 этап. Мониторинг

Для мониторинга системы можно применять elk+ prometuse.

Для трассировки запросов — opentelemetry.

В рамках MVP реализация не выполнялась.

Итог:

Конечный вариант архитектуры проекта:

Создание архитектуры платформы для сбора, обработки и хранения данных от IoT-устройств

Highload_970x90-1801-fc90a0.png