MAATRIX / Блог / ThingsBoard обещает IoT из коробки — у коробки обнаруживаются стенки

ThingsBoard обещает IoT из коробки — у коробки обнаруживаются стенки

MAATRIX

ThingsBoard обещает закрыть весь IoT-стек одним развёртыванием: приём телеметрии с любых устройств, правила обработки данных, дашборды, управление устройствами и алерты. Обещание честное — платформа действительно всё это умеет. Но в документации не говорят прямо: за один Docker-контейнер с настройками по умолчанию вы получите систему, которая захлебнётся на первой же сотне устройств, шлющих телеметрию раз в минуту. ThingsBoard — это не «поставили и работает», это полноценная система с базой под серьёзную нагрузку, брокером сообщений и правильно посчитанными ресурсами под движок правил в реальном времени.

Что на самом деле делает ThingsBoard

Три модуля составляют ядро платформы, и от их нагрузки на инфраструктуру зависит всё остальное.

Сбор телеметрии. Устройства подключаются по MQTT, CoAP, HTTP или через собственный протокол ThingsBoard поверх gRPC. Каждое сообщение — это одна или несколько временных меток с набором значений (температура, влажность, уровень заряда, координаты, что угодно). При тысяче устройств с интервалом в минуту это уже более десятка миллионов точек в сутки, и каждая должна лечь в базу с индексом по времени и по устройству, чтобы дашборд потом отрисовался за разумное время.

Rule Engine — движок правил. Это сердце платформы: граф узлов, через который проходит каждое входящее сообщение. Узел может отфильтровать сообщение по условию, трансформировать его через JavaScript-функцию, сохранить в базу, отправить алерт или переслать дальше. Именно rule engine превращает сырую телеметрию в события: «температура выше порога три раза подряд — создать алярм», «устройство не присылало данных 15 минут — пометить как offline». Каждое правило исполняется синхронно относительно потока сообщений, и при росте числа устройств это первое место, где вы упрётесь в CPU, а не в диск.

Дашборды и управление устройствами. Виджеты тянут данные напрямую из базы телеметрии через отдельный API, и на сложных дашбордах с десятками виджетов и диапазоном «за месяц» это уже не точечные SELECT, а агрегирующие запросы по миллионам строк. Плюс к этому — иерархия устройств, ассеты (группировка по объектам: здание → этаж → комната → датчик), профили устройств с шаблонами алармов.

Отдельно есть слой очереди сообщений между этими компонентами — по умолчанию in-memory, но для чего-то серьёзнее демо-стенда нужен внешний брокер. Разберём каждый узел инфраструктуры по порядку.

База данных: где реально упирается телеметрия

ThingsBoard хранит два типа данных раздельно, и это ключевое архитектурное решение, определяющее выбор СУБД.

Метаданные — устройства, ассеты, пользователи, права, шаблоны дашбордов, настройки алармов — идут в реляционную базу, практически всегда PostgreSQL. Нагрузка здесь типична для любого веб-приложения: если вы уже настраивали PostgreSQL на VPS, ничего экзотического не будет.

Телеметрия — временные ряды с показаниями устройств — это другая история. По умолчанию ThingsBoard кладёт её в ту же PostgreSQL, в таблицу ts_kv, партиционированную по времени. На небольшом парке устройств (условно — до пары сотен, шлющих данные раз в минуту-две) это работает без нареканий: обычная таблица с составным индексом, обычный VACUUM, обычный бэкап. Но телеметрия растёт линейно и без остановки — это постоянный поток вставок, а не транзакционные данные, которые устаревают и удаляются. Через несколько месяцев непрерывной работы таблица ts_kv на паре тысяч устройств легко разрастается до сотен миллионов строк, и обычная PostgreSQL начинает деградировать и на записи, и на агрегирующих выборках для дашбордов.

Здесь у вас три пути:

  1. PostgreSQL с расширением TimescaleDB. ThingsBoard поддерживает этот режим из коробки — при установке достаточно выбрать вариант «PostgreSQL + Timescale». Timescale превращает ts_kv в гипертаблицу с автоматическим партиционированием по времени (chunks), что заметно ускоряет и вставку, и запросы по диапазону дат — именно то, что нужно дашбордам. Это практичный выбор для среднего парка устройств: вы остаётесь в экосистеме PostgreSQL (те же бэкапы, тот же SQL для отладки), но получаете производительность временных рядов — та же идея, что в сравнении TimescaleDB и InfluxDB, только здесь Timescale встроена как штатный режим платформы.
  1. Cassandra (отдельно или в гибриде с PostgreSQL для метаданных). Для по-настоящему больших объёмов — десятки тысяч устройств, высокая частота отправки — ThingsBoard поддерживает Cassandra как хранилище телеметрии: она спроектирована под write-heavy нагрузку и горизонтальное масштабирование. Плата — отдельный кластер, который нужно администрировать: без опыта эксплуатации Cassandra это создаёт больше проблем, чем решает.

Для подавляющего большинства проектов правильный ответ — PostgreSQL + TimescaleDB. Он не требует отдельного кластера, покрывает диапазон от сотен до нескольких тысяч устройств и остаётся управляемым одним администратором. Переходить на Cassandra стоит только когда вы уже упёрлись в лимиты Timescale на конкретных метриках — не заранее «на всякий случай».

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS под ThingsBoard

Брокер сообщений: зачем он, если есть встроенная очередь

У ThingsBoard есть внутренняя in-memory очередь для передачи сообщений между микросервисами платформы (транспортный слой → core → rule engine). Она работает «из коробки», и для одного инстанса на небольшой нагрузке этого достаточно — это то, что вы получите, поднимая ThingsBoard одной командой docker run по официальному quick-start.

Проблема в том, что in-memory очередь живёт и умирает вместе с процессом. Если контейнер перезапускается (обновление, авария, docker-compose restart), все сообщения в очереди на обработку теряются. Для демо-стенда это не страшно. Для продакшна, где потеря телеметрии равна потере данных с реальных устройств, это неприемлемо.

Поэтому в production-конфигурации ThingsBoard используется внешний брокер:

  • Kafka — официально рекомендуемый вариант, и самый требовательный по ресурсам. Даёт персистентность сообщений, replay при сбоях, масштабирование партициями. Если вы уже разворачивали Kafka на VPS, то представляете порядок цифр: даже минимальный одноброкерный кластер — отдельный процесс с собственными требованиями к памяти и диску, которые закладываются отдельно от расчёта под платформу.
  • RabbitMQ — легче в администрировании и ресурсоёмкости, но менее гибок при масштабировании и не даёт такого же replay, как Kafka.
  • AWS SQS / Google Pub/Sub — управляемые опции для облака соответствующего провайдера; на своём VPS не применимы напрямую.

Практический вывод: для пары десятков устройств «на попробовать» встроенной очереди достаточно, не усложняйте. Как только речь заходит о продакшне с деньгами или безопасностью на кону — закладывайте Kafka сразу, потому что миграция очереди на уже работающей системе с накопленными данными — отдельная и не самая приятная задача.

Rule Engine: где упирается CPU, а не диск

Это тот компонент, о котором чаще всего забывают при планировании ресурсов, — интуитивно кажется, что раз данные «просто проходят через систему», нагрузка должна быть небольшой. На практике каждое сообщение телеметрии проходит через граф правил синхронно, и если в цепочке есть JavaScript-трансформация (стандартный узел для нормализации данных — привести единицы измерения, посчитать производную метрику, отфильтровать выбросы), выполняется он в embedded JS-движке на JVM — ощутимо дороже по CPU, чем просто INSERT в базу. Это умножается на количество активных правил и на частоту сообщений: несколько тысяч устройств с интервалом отправки в десятки секунд легко дают десятки сообщений в секунду и заметные пики, когда устройства просыпаются синхронно по одному расписанию — нагрузка на движок правил, отдельная от нагрузки на базу.

Что с этим делать на практике:

  • Держите правила простыми там, где можно. Фильтрацию по типу сообщения делайте на уровне профиля устройства, а не внутри JS-скрипта — это дешевле.
  • Разносите тяжёлую логику. Если правило должно дёрнуть внешний API или выполнить сложные вычисления — используйте асинхронные узлы (rest-api-call, очередь) вместо синхронной обработки в основном потоке.
  • Мониторьте очередь rule engine отдельно. ThingsBoard экспортирует метрики через встроенный endpoint — важно видеть именно глубину очереди правил, а не только CPU и память процесса, потому что рост очереди сообщений сигнализирует, что rule engine не успевает за потоком, задолго до того как это станет заметно на дашбордах.

Микросервисная архитектура ThingsBoard (core, transport и rule engine можно развернуть как отдельные сервисы) существует именно для того, чтобы масштабировать rule engine независимо от остальной платформы. Для одного VPS это избыточно — проще выделить больше CPU монолитному инстансу. Разносить компоненты имеет смысл, когда видно, что узкое место — конкретно rule engine, а не база или сеть.

Сколько ресурсов заложить на практике

Точных цифр «под ключ» никто не даст — сильно зависит от частоты телеметрии, сложности правил и глубины истории на дашбордах. Порядок величин как ориентир, который нужно скорректировать под свою нагрузку:

СценарийУстройстваТелеметрияБДБрокерПримерный VPS
Пилот / лабораториядо 50раз в 1-5 минPostgreSQLвстроенная очередь2 vCPU, 4 ГБ RAM
Малый продакшн100-500раз в минутуPostgreSQL + TimescaleDBвстроенная очередь или RabbitMQ4 vCPU, 8 ГБ RAM
Средний продакшн500-3000раз в 30-60 секPostgreSQL + TimescaleDBKafka (отдельный узел или процесс)8 vCPU, 16 ГБ RAM + отдельный узел под Kafka
Крупный парк3000+высокая частотаCassandra или гибридKafka-кластернесколько узлов, распределённая архитектура

Это ориентировочная таблица, а не расчёт под вашу нагрузку — конкретные цифры будут отличаться в зависимости от того, сколько метрик передаёт каждое устройство за одно сообщение и сколько виджетов строят агрегаты по длинным диапазонам. Отдельно стоит вопрос про JVM: ThingsBoard написан на Java, и по умолчанию heap настроен консервативно — на реальной нагрузке его нужно поднимать явным образом через JAVA_OPTS, иначе получите GC-паузы на пиках, которые выглядят как случайные подвисания дашборда. Принцип простой: JVM heap плюс база плюс брокер плюс нужды ОС не должны конкурировать за одни и те же 4 ГБ — память нужно закладывать с запасом, а не впритык.

Развёртывание: Docker Compose и что в нём должно быть с самого начала

Официальный образ thingsboard/tb-postgres — хороший старт, но docker-compose из quick-start документации рассчитан на демо, а не на продакшн. Минимальный рабочий compose-файл для варианта PostgreSQL + TimescaleDB:

services:
  thingsboard:
    image: thingsboard/tb-postgres:latest
    restart: unless-stopped
    ports:
      - "8080:9090"
      - "1883:1883"
      - "7070:7070"
      - "5683-5688:5683-5688/udp"
    environment:
      TB_QUEUE_TYPE: kafka
      TB_KAFKA_SERVERS: kafka:9092
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/thingsboard
      SPRING_DATASOURCE_PASSWORD: ${TB_DB_PASSWORD}
      JAVA_OPTS: "-Xms2g -Xmx4g"
    volumes:
      - tb-data:/data
    depends_on: [postgres, kafka]

  postgres:
    image: timescale/timescaledb:latest-pg15
    restart: unless-stopped
    environment:
      POSTGRES_DB: thingsboard
      POSTGRES_PASSWORD: ${TB_DB_PASSWORD}
    volumes:
      - pg-data:/var/lib/postgresql/data

  kafka:
    image: bitnami/kafka:latest
    restart: unless-stopped
    environment:
      KAFKA_CFG_PROCESS_ROLES: broker,controller
      KAFKA_CFG_NODE_ID: 1
    volumes:
      - kafka-data:/bitnami/kafka

volumes:
  tb-data:
  pg-data:
  kafka-data:

Три момента, которых часто не хватает в примерах из интернета: пароль вынесен в переменную окружения, а не зашит текстом в YAML; явно заданы JAVA_OPTS с реальным heap; и TB_QUEUE_TYPE: kafka вместо встроенной очереди с самого начала — переключать тип очереди на живой системе с накопленными сообщениями заметно неприятнее, чем сразу выбрать правильный вариант. Порты: 1883 — MQTT, 5683-5688/udp — CoAP, 7070 — gRPC-транспорт, 8080 — веб-интерфейс и REST API. Если устройства ходят через интернет напрямую на сервер, MQTT и CoAP нужно защищать отдельно — TLS для MQTT обязателен вне лабораторных условий, иначе телеметрия и команды идут открытым текстом.

Кому это действительно нужно, а кому — нет

ThingsBoard оправдан, когда у вас разнородный парк устройств — не один тип сенсора, а смесь: температурные датчики, счётчики, GPS-модули, промышленные контроллеры по Modbus через шлюз — и нужна единая точка для правил, дашбордов и алармов поверх всего этого разнообразия. Также он оправдан, когда бизнес-логика завязана на правилах обработки в реальном времени: не «показать график», а «температура в холодильной камере выше порога дольше 10 минут — отправить SMS и создать инцидент».

Если у вас узкая задача под один тип устройств, специализированное решение почти всегда экономичнее по ресурсам и проще в администрировании. Например, для GPS-трекеров транспорта — координаты, треки, геозоны, отчёты по пробегу — есть предметно заточенные системы вроде Traccar, которые не тащат за собой универсальный rule engine и произвольную схему телеметрии: изначально спроектированы под один протокол данных и один сценарий использования. Разница принципиальная: ThingsBoard — универсальная платформа для произвольных датчиков с гибким конструктором правил, специализированная система — оптимизированное решение под конкретный класс устройств с меньшими требованиями к железу и администрированию. Если у вас именно транспортный мониторинг, история с собственным сервером GPS-мониторинга для транспортной компании показывает, во что это выливается на практике без универсальной IoT-платформы поверх.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS под ThingsBoard

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли начать с встроенной in-memory очереди и позже перейти на Kafka без потери данных?

Технически да — переключение TB_QUEUE_TYPE не требует переустановки платформы, но накопленные в старой очереди неподтверждённые сообщения не переносятся автоматически. Если потеря телеметрии за короткое окно переключения для вас некритична, можно мигрировать позже. Если критично — закладывайте Kafka сразу.

Обязательно ли использовать TimescaleDB, или подойдёт чистый PostgreSQL?

Чистый PostgreSQL подойдёт для небольшого парка устройств и невысокой частоты телеметрии. Проблемы начинаются, когда таблица ts_kv разрастается до десятков-сотен миллионов строк: без партиционирования по времени и запросы на дашборды, и вставка новых точек заметно замедляются. TimescaleDB решает это встроенным партиционированием без смены СУБД.

Сколько устройств потянет один VPS без кластеризации?

Однозначного числа нет — зависит от частоты телеметрии и сложности правил, но диапазон в несколько тысяч устройств с телеметрией раз в минуту на хорошо настроенном сервере (8-16 ГБ RAM, несколько vCPU) обычно достижим без разнесения компонентов на отдельные узлы. Точную цифру для своего случая вы получите только нагрузочным тестированием.

Что произойдёт, если не настроить TLS для MQTT?

Телеметрия и команды устройствам пойдут открытым текстом, включая пароли устройств для аутентификации в брокере. Для лабораторного стенда в изолированной сети это допустимо, для устройств, обращающихся к серверу через интернет, — нет.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →