MQTT — протокол, на котором держится почти весь современный умный дом и промышленный интернет вещей. Устройства не общаются напрямую: они публикуют значения в именованные темы на центральном сервере — брокере, — а те, кому эти значения нужны, на темы подписываются. Брокер получается сердцем системы: если он лежит, молчит весь объект. Поэтому вопрос «какой брокер поставить» — не праздный.
Мы разрабатываем оборудование и программное обеспечение для умного дома, и брокер нам нужен был свой: с понятной панелью, предсказуемым поведением и без зависимостей, которые нужно поддерживать годами. Так появился ELX-MQTT Broker — он бесплатный, не ограничен по числу устройств и сообщений, и его можно использовать в любых проектах, включая коммерческие.
Что такое MQTT-брокер и зачем он в умном доме
MQTT работает по модели «издатель — подписчик». Датчик температуры публикует значение в тему вида home/hall/temperature, а подписаны на неё могут быть сразу несколько получателей: мобильное приложение, дашборд, сценарий автоматизации, голосовой ассистент. Ни один из них не знает про датчик ничего, кроме имени темы, — и это главное достоинство протокола: систему можно наращивать, не переписывая то, что уже работает.
Всю эту развязку и обеспечивает брокер. Он принимает подключения, проверяет права, хранит последние значения (retain), доставляет сообщения с гарантией нужного уровня, помнит подписки отключившихся клиентов и рассылает «последнюю волю» (Last Will) тех, кто пропал со связи. В умном доме на брокере завязано буквально всё: команды на реле, состояния датчиков, климат, сценарии, интеграция с внешними сервисами.
Классический выбор — Mosquitto или EMQX. Первый прост, но настраивается только файлами конфигурации, а увидеть, что происходит внутри, нечем: приходится ловить события подписчиком-отладчиком. Второй мощный, но тяжёлый: Erlang, память, обвязка — на объектовой машине или одноплатнике это избыточно. Нам хотелось третьего варианта: маленького брокера, который ставится за минуту и при этом показывает своё состояние в браузере.
Что внутри: протокол реализован с нуля
Брокер написан на Go, и протокол в нём реализован полностью самостоятельно — ни одной сторонней MQTT-библиотеки. Кодек разбирает и собирает все 15 типов пакетов, проверяет границы Variable Byte Integer, дубли свойств и зарезервированные биты. Это не самоцель: своя реализация означает, что любое расхождение с устройством разбирается по коду, а не по чужому багтрекеру.
Поддержаны сразу две версии протокола, и они работают одновременно на одном порту: старое устройство подключается по MQTT 3.1.1, новое — по MQTT 5.0, и они свободно обмениваются сообщениями. Для существующих объектов это важно: контроллеры и модули живут долго, и переводить их разом на новую версию никто не станет.
- QoS 0, 1 и 2 — полные рукопожатия, подавление дублей на QoS 2 и переотправка незавершённых обменов после переподключения. Оффлайн-очереди постоянных сессий переживают перезапуск брокера.
- Retain и Last Will — хранилище последних значений с очисткой пустым payload, Retain Handling 0/1/2, Retain As Published; «последняя воля» отправляется во всех сценариях разрыва, включая отложенную Will Delay Interval из пятой версии.
- Возможности MQTT 5.0 — псевдонимы тем, Session Expiry, Receive Maximum и контроль потока, идентификаторы подписок, общие подписки
$share, No Local, Message Expiry, Content Type, Response Topic, Correlation Data, User Properties, коды причин во всех пакетах, серверный DISCONNECT и пакет AUTH. - Системные темы
$SYS— версия, аптайм, счётчики клиентов, сообщений, байт и ошибок. Ветка закрыта по умолчанию: подстановки до неё не достают, анонимным клиентам весь namespace запрещён, а публикацию целиком можно выключить рубильником в настройках.
Живая веб-панель вместо чтения логов
Главное отличие от привычных брокеров — панель, которая показывает происходящее в реальном времени. Она обновляется потоком по WebSocket, без перезагрузок страницы: видно сводку по клиентам и сессиям, состояние машины (процессор, память, диск раздела с данными), графики скорости сообщений и трафика, активные темы и ленту событий.
Отдельные разделы отведены под клиентов (таблица сессий с карточкой клиента, отключением и удалением сессии), подписки со всеми опциями пятой версии и содержимое retain-хранилища. Живой поток сообщений можно фильтровать и ставить на паузу, а из панели — опубликовать своё сообщение со всеми свойствами MQTT 5.0. На отладке устройства это экономит часы: не нужно писать тестовый скрипт, чтобы проверить, что именно приходит и в каком формате.
Интерфейс переведён на семь языков (русский, английский, немецкий, испанский, французский, итальянский и китайский), темы две — тёмная и светлая, переключаются на лету. Справка встроена прямо в панель и описывает ровно ту версию, которая у вас установлена.
Доступ и безопасность
В брокере два независимых контура доступа. Администратор панели один, он задаётся в config.json и управляет только веб-интерфейсом. MQTT-устройства — отдельный список учётных записей со своими паролями и правами; завести MQTT-пользователя с именем администратора нельзя. Это сознательное разделение: скомпрометированный датчик не должен открывать доступ к настройкам брокера.
Права раздаются правилами ACL по темам. Правило — это фильтр, доступ (чтение, запись или и то, и другое) и разрешение либо запрет; проверка идёт сверху вниз до первого совпадения, всё остальное запрещено по умолчанию. Плейсхолдер $u разворачивается в имя клиента, поэтому одно правило $u/# замыкает каждое устройство в его собственной ветке — на объекте с десятками модулей это экономит десятки правил.
- Шесть источников учётных записей: внутренний список, MySQL/MariaDB (схема в стиле EMQX), SQLite, CSV с перечитыванием файла, JWT и внешний HTTP-сервис. Источник переключается в панели: сначала проверяется кнопкой, потом применяется на лету.
- Хеши, а не пароли: PBKDF2-HMAC-SHA256 с 210 000 итераций и случайной солью, токены сессий и API хранятся только в виде хешей. Внешние источники понимают plain, sha256, sha512, bcrypt и pbkdf2.
- TLS из коробки: самоподписанный сертификат создаётся при первом запуске, чтобы порт 8883 работал сразу; для продакшена подставляется свой.
Правила, лимиты и отложенная публикация
Реальные объекты редко бывают идеальными: одно устройство шлёт слишком часто, другое требует «свою» схему тем, третье не умеет подписываться само. Для таких случаев в брокере есть механизмы, которые обычно приходится доделывать скриптами.
- Перезапись тем. Имя темы подменяется на лету при публикации, подписке или всегда: сначала дешёвый отбор MQTT-фильтром, затем регулярное выражение и шаблон новой темы с группами
$1…$9. В панели есть песочница, где правило проверяется до применения. - Автоподписка. Клиент получает подписки сразу после подключения, без SUBSCRIBE. Права ACL при этом проверяются как обычно: запрещённое правило молча пропускается, соединение не рвётся.
- Ограничения по темам. Поток прореживается до нормы с сохранением последнего значения: датчик, который шлёт десять раз в секунду, превращается в одно сообщение в секунду — самое свежее. Видно, сколько сообщений совпало с правилом, сколько прошло и сколько отброшено.
- Защита от флуда. Token bucket на каждое подключение — сообщений в секунду, всплеск, байт в секунду. Превышение не рвёт соединение и не теряет сообщения: брокер делает паузу перед следующим чтением из сокета, TCP закрывает окно, и отправитель замедляется сам.
- Отложенная публикация. Тема
$delayed/60/дом/светпридерживается брокером на заданное время (от секунды до 49 суток), совместимо с EMQX. Очередь переживает перезапуск и видна в панели с обратным отсчётом.
Интеграция: мост, REST API и WebSocket
Брокер умеет работать мостом: подключаться как клиент к другому MQTT-брокеру и пересылать темы в обе стороны. Настраиваются адрес, логин, TLS, версия протокола и правила «фильтр + направление + QoS + префиксы»; есть защита от петель, авто-переподключение и счётчики в панели. Типичный сценарий для умного дома — локальный брокер на объекте и облачный брокер снаружи: внутри дома всё работает даже без интернета, а наружу уезжает ровно то, что нужно.
Весь функционал панели доступен по REST API с bearer-токеном: статистика, клиенты, подписки, retain, публикация, события, пользователи, настройки, мосты, правила, отложенные сообщения, импорт и экспорт. Токен можно выдать только на чтение — удобно для мониторинга. Отдельно стоит отметить управление устройствами из своей системы: POST /api/users заводит устройство вместе с правами, PATCH меняет пароль или ACL, DELETE удаляет, и изменения применяются мгновенно — брокер сам разрывает живые соединения этого пользователя, чтобы новые правила действовали сразу.
Для браузерных клиентов есть MQTT over WebSocket: подпротокол mqtt работает на том же порту, что и панель, отдельный шлюз не нужен. Настройки, пользователей и правила можно выгрузить одним файлом и загрузить на другом сервере — перенос не требует ручного повторения.
Проверено под нагрузкой
Брокер прогонялся стресс-тестами на двух стендах — по сети и по loopback, — чтобы отделить свойства самого брокера от влияния окружения. Тестировал собственный нагрузочный клиент на том же кодеке, без сторонних библиотек.
| Метрика | По сети (12 ядер) | Loopback (28 ядер) |
|---|---|---|
| Соединений без единого отказа | 10 000 | 30 000 |
| Приём QoS 0 (64 Б), пик | 271 006 сообщ./с | 185 012 сообщ./с |
| Сквозная задержка, медиана | 1,0 мс | 73 мкс (среднее) |
| Доставка при fan-out ×100, пик | 22 351 сообщ./с | 1 353 431 сообщ./с |
| Ошибки в логе брокера | нет | нет |
Цифры стендов не эквивалентны и отвечают на разные вопросы: на loopback генератор нагрузки делит ядра с брокером, зато нет сети. Практический вывод простой: для домашнего или объектового применения запас по производительности избыточный — типичный объект умного дома это десятки устройств и сотни сообщений в секунду. Полная методика, таблицы и команды для воспроизведения опубликованы на странице нагрузочного тестирования.
Установка и порты
Брокер — один статически слинкованный бинарник: ни runtime, ни libc, ни внешней базы. Данные хранятся в SQLite рядом. Поддерживаются Debian и Ubuntu (amd64, arm64, armhf) и Windows x64 — то есть и сервер, и Raspberry Pi, и Orange Pi в щите. Ставится из APT-репозитория одной командой:
sudo apt-get install elxmqttbroker
После установки сервис поднимается сам и сразу слушает четыре точки входа:
:1883— MQTT по TCP;:8883— MQTT по TLS;:8567— веб-панель;:8567/mqtt— MQTT по WebSocket.
В комплекте идут юнит systemd, конфиг nginx и идемпотентный установочный скрипт: панель слушает только localhost и открывается наружу через nginx, а MQTT-порты работают напрямую. Версия, номер сборки и время сборки вшиты в бинарник и видны в панели — всегда понятно, что именно запущено.
Попробовать без установки. У проекта есть публичный демо-брокер: demo.elxmqtt.com:1883, учётные данные demo / demo12345. К нему можно подключиться любым клиентом и посмотреть, как ведут себя темы и retain, прежде чем ставить брокер себе.
Кому это пригодится
Инсталляторам. На объекте нужен локальный брокер, который переживёт пропажу интернета и не потребует отдельного сервера. Панель заодно закрывает вопрос «а доходят ли команды»: видно и подключение модуля, и сами сообщения.
Разработчикам и интеграторам. REST API позволяет заводить устройства и права прямо из своей системы, ACL с $u изолирует клиентов друг от друга, мост связывает объект с облаком. Всё это без лицензий и ограничений по числу подключений.
Энтузиастам умного дома. Home Assistant, Node-RED, OpenHAB, ESPHome и самодельные устройства на ESP32 подключаются к брокеру как к любому другому — это стандартный MQTT. Разница в том, что происходящее видно в браузере, а не только в логах.
Итог
ELX-MQTT Broker закрывает вполне конкретный пробел: полноценный брокер со всеми возможностями пятой версии протокола, но с человеческой панелью и установкой в одну команду. Он бесплатен целиком, без ограничений по числу устройств, сообщений и подписок, и его можно применять в коммерческих проектах. Скачать, посмотреть скриншоты и документацию можно на elxmqtt.ru, а остальные наши бесплатные инструменты собраны на странице «Полезное».