MQTTについて少し

ParticleでQoS1|2を実装しれ!!みたいに言われて、それっぽく使いやすいように実装してみたりして思ったりする所。Spark/Photonを持っている人なら一度は使ったと思われるMQTT、なぜかIoT(的)な物で使われるMQTT…に対してQoSを意識して実装する時の注意点を少し。

MQTT QoS0|1|2のシーケンスは以下の通り。

ここではよく利用すると思われるPUBLISHを例にする。MQTTはQoSのレベルによって接続するMQTTサーバとの通信が変わる。レベルが上がる毎に、応答確認(ACK)メッセージのやり取りが増える感じ。このACKを利用すると、次のような実装が期待されると思う。

これはQoS1の場合について。timer処理を入れて、ACKが来なかった時に同じメッセージを再送するといった事ができるようになる。実際MQTT 3.1のプロトコル定義にもDUPフラグを付けて再送信処理を行うと記載されている。(MQTT V3.1 Protocol Specification, 4.1. Quality of Service levels and flows, QoS level 1: At least once deliveryから)
NWの一般的なQoS(流量制御や遅延への保証)とは違って、メッセージの到達保証にかかるシーケンスが変わる感じですね。ここで、自分的にはこのtimer処理を入れて再送するという実装をしている場合は、それは止めた方が良いと思われ。そう言ったクライアントを利用しているなら、ちょっと危ない気はする。ちなみに、サーバ側はACKを送って、その再送処理を行わないのが殆どだと思われ(その必要がない)。

というのはTCP over TCP問題(Why TCP Over TCP Is A Bad Idea)という、よくある問題がベースになる。短い資料だけど、遅い&遅延が発生するようなNW(特にIoT的な端末だと、低帯域なNWを利用すると思われるので、このケースがよく合う)で発生する問題で一度は目を通した事がある人も多いはず。ザックリだと、TCPの上に信頼性(再送を行うような)のあるプロトコルを載せた場合、そのNWは破綻するといった感じ。

MQTTは足回りにTCPを利用していて、QoS1|2のケースでメッセージの到達性の確認(ACK)を利用した再送処理を行う場合、同様の問題(輻輳)が発生する可能性がある。上位(MQTT)の再送処理が、足回りTCPの再送を更に増加させて、輻輳により結果として止まってしまう現象が起きる。条件としては。

1. QoS1|2を利用
2. 到達性の保証からACK待ちのタイマーでの再送を行う

この場合に発生する現象です。これを回避するには、

1. タイマーによる再送を行わない
2. QoS0を利用する
3. 必要な時だけ接続断

このくらいかしら。MQTTのプロトコル的にはQoS1|2を利用するとき、ACKを受け取れない場合、Sender(クライアント)はDUPフラグを付けて再送信する。これは足回りにTCPを利用するケース(MQTT-SN: UDP/non-IPの実装をしている場合は別)では止めた方が良い。再送信が1回だけならOK…な感じも少しするけど、送信する頻度、TCP接続の維持(は止めた方が良い気がする)などで、どういった実装をするか不明なので再送信が1回も10回も変わらない。結果としてタイマー処理を行うようあるにも関わらず使わない方が良いという事になる。これは違和感もあると思うけど、プロトコル定義と発生する現象は別なので。
ちなみにTCPを利用するのはNWの信頼性のためで、上位MQTTメッセージングの信頼性はMQTTとして保証する必要があるため、別々のレイヤーとして考えられる。そのため、MQTTとしてはACKが必要になるというのも理解が出来る。ただ、どちらかと言えば、HTTP(リクエスト・レスポンス、トランザクションレス)のようなACKとして考えた方が良いと思われる。MQTTとHTTPで比較がたまにあるように、HTTPのように再送信を意識したり期待はしない方が良い。

経験的にだけど、回線業者と専用線で帯域保証を付けているNWでない限り、インターネットはベストエフォートな世界なので、遅延や低帯域になる事は普通にあり得る。そういった所で、足回りがTCPで再送処理を行う時の注意点としても、一つ考えておいた方が良いと思われ。
同様にIoT的なプロトコルの一つにCoAPがあるけど、そっちは足回りがUDPでこのような事は考える必要がない。あと、Google Chromeに実装されているQUICなんかも足回りはUDPで、その上に独自に信頼性のあるプロトコルを構築する形になっている。上位と下位のNWで何を利用して、どういう実装をするか?と言うのは、その後に発生するであろう問題点の回避として、一考しておいて良いでしょう。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください