DevUA

Meta


Paho MQTT кліент, Quality of Service > 0 та max in-flight messages

Микола МахінМикола Махін

Протокол MQTT набирає все більшої популярності у зв’язку з поширенням і популяризацією IoT та SmartHome рішень і технологій (наприклад послуги MQTT брокера надає серед інших Amazon).

Робота з протоколом MQTT для Java розробника часто означає використання в якості MQTT клієнта FOSS бібліотеки Eclipse Paho, яка, напрклад, штатно йде з Spring Messaging.

В роботі з Paho при відправці великої кількості повідомлень за короткий проміжок часу може виникати помилка “Too many publishes in progress“, причина якої полягає в наступному: при відправці з Quality of Service більше за 0 (нуль) кожне відправлене MQTT брокеру повідомлення має бути збережене поки брокер не підтвердить отримання, і перевідправлене якщо брокер не підтвердив отримання повідомлення за якийсь період часу. Збережені непідтверджені повідомлення називаються в термінології Paho in-flight, і кількість таких повідомлень обмежена.

Звичайно, найпростішим і гарантованим способом уникнути цієї помилки є використання нульового рівня Quality of Service. Але є і інші варіанти.

Paho підтримує два варіанти збереження in-flight повідомлень – в пам’яті та в файлі. Але обидва варіанти збереження повідомлень in-flight по замовчуванню обмежені… 10 повідомленнями. Тобто якщо 10 повідомлень є в даний момент часу in-flight і треба відправити 11-е з Quality of Service більше за нуль – Paho поверне помилку (виключення) Too many publishes in progress.

На мою думку 10 це якось дуже скромно. Але змінити це значення не можна було аж до версії Paho 1.1.0, яка була випущена зовсім не так вже давно – в кінці січня 2015-го. Якщо ви вважаєте що це досить таки давно – подивіться на javadoc-и до Paho на сайті Eclipse – там досі версія 1.0.0, і зміни стосовно max in-flight messages в javadoc-ах по Paho банально не відображені.

А зміни в API власне такі – в класі org.eclipse.paho.client.mqttv3.MqttConnectOptions з’явився метод:

public void setMaxInflight(int maxInflight)

за допомогою якого можна задати максимальну кількість in-fligh повідомлень.

В обговореннях проблеми я знаходив згадки що обмеження на максимум in-flight по MQTT протоколу – 65535 повідомлень. Набагато щєдріше ніж 10, погодьтесь. Хоча насправді в стандарті MQTT протоколу я такого обмеження не побачив (в один момент часу може бути тільки одне in-flight повідомлення спільне для клієнта і брокера – всі решта чекають з боку клієнта, і їх кількість обмежена лише можливостями клієнта). Але в Paho є обмеження на ідентифікатори повідомлень – від 1 до 65535, яке пов’язане з тим, що кожному “пакету” в MQTT при Quality of Service більше нуля має відповідати певний 16-бітний ідентифікатор. Я не впевнений чому ідентифікатор повідомленню має видаватись вже тоді коли воно попадає в чергу відправки, тобто стає in-flight з точки зору клієнта, але ще не доходить до брокера – мабуть це особливості імплементації від Paho.

Але так чи інакше – при встановленні max in-flight більше за 65535 Paho може (і буде) видавати іншу помилку – “Internal error, caused by no new message IDs being available“. Більше того, т.я. це стосується всіх “пакетів” – деякі ID забирають сервісні MQTT повідомлення (ping, ack, т.п.), тому можливо не варто виставляти максимум власне в 65535, а трохи нижчий – щоб уникнути вищеназваної помилки.

Ось наразі і все, сподіваюсь ця стаття допомогла Вам.