четверг, 7 апреля 2016 г.

[prog.mqtt] Интересная багофича MQTT, QoS=0 и pingreq/pingresp

Обнаружил интересную багофичу протокола MQTT. Если некоторый клиент подключается к брокеру и подписывается на некоторый топик с Quality-of-Service=0 (т.е. доставка сообщений не гарантируется), то в случае отсутствия сообщений в этом топике клиент и брокер будут обмениваться pingreq/pingresp-ами. И соединение будет продолжать жить, т.к. оно доказывает свою жизнеспособность этими самыми регулярными ping-ами.

Однако, если в топике появляется сообщение, оно доставляется до клиента посредством publish PDU. Но в ответ клиент ничего не отсылает, т.к. QoS=0 (при этом QoS подтверждения доставки не требуется). И здесь оказывается забавная ситуация: клиент видит у себя активность в канале и начинает отсчет времени для следующего pingreq заново. Т.е. клиент инициирует следующий pingreq через N секунд после получения publish, а не через N секунд после выдачи последнего pingreq. Т.е. если последний pingreq был в момент времени T(0), а publish пришел в момент времени T(1), то следующий pingreq от клиента уйдет в (T(1)+N).

А вот брокер ничего не видит от клиента. Брокер знает только про последний pingreq, полученный в момент времени T(0). И рассчитывает получить следующий в (T(0)+N). Но этого pingreq-а не будет, т.к. клиент отошлет его только в (T(1)+N). Поэтому в (T(0)+N) сервер решит, что клиент умер, а соединение "протухло". Что даст ему право соединение с клиентом разорвать.

Получается, что если некоторый клиент подключается к MQTT-брокеру только для того, чтобы слушать какие-то топики с QoS=0, но ничего не публиковать (например, клиент слушает $SYS-топики), то связь клиента с брокером может рваться на регулярной основе.

Причем, по стандарту, pingreq может отсылать только клиент. Брокер этого не делает. А если бы делал, то этой проблемы бы не было, просто брокер отослал бы pingreq сам, получил бы pingresp и понял бы, что клиент жив-здоров. Но нет, современный MQTT-протокол вот такой.

PS. Вообще, реальное погружение в работу с MQTT оставляет несколько странные впечатления. Иногда кажется, что либо ты слишком тупой, чтобы осознать всю силу сирости и убогости простоты, либо "простота хуже воровства" -- это довольно точная характеристика.

PPS. Не знаю, как на счет реализаций MQTT для других современных языков, но вот C-шные libmosquitto и Paho оставляют ощущение, что они были написаны для каких-то ну очень примитивных сценариев использования.

Комментариев нет: