Skip to content

In-flight とメッセージキュー

はじめに

メッセージのスループットを向上させ、ネットワークの変動による影響を軽減するために、EMQX は複数の未アック(未確認)の QoS 1 および QoS 2 メッセージを同時に In-flight 状態で保持できます。送信済みでまだ確認されていないこれらのメッセージは、アックが完了するまで Inflight Window に保存されます。

In-flight メッセージの数が制限を超えた、すなわち Inflight Window の長さ制限(max_inflight を参照)に達した場合、EMQX はそれ以降のメッセージを送信せず、これらのメッセージをメッセージキューに格納します。Inflight Window 内のメッセージがアックされると、メッセージキュー内のメッセージは先入れ先出し(FIFO)順に送信され、Inflight Window に格納されます。

QoS 1、2 の In-flight メッセージ数が Inflight Window の最大制限(max_inflight を参照)に達すると、新たに到着したメッセージはすぐに転送されず、一時的にメッセージキューに保存されます。

メッセージキュー内のメッセージは FIFO 順に送信され、前のメッセージが確認されて削除された後にのみ Inflight Window に追加されます。ただし、QoS 0 メッセージはこのプロセスの影響を受けず、常に即座に転送されます。

メッセージキューも長さ制限に達した場合、それ以降のメッセージは引き続きメッセージキューにキャッシュされますが、メッセージキュー内の最も古いメッセージが破棄されます。したがって、適切なメッセージキューの長さ制限(max_mqueue_len を参照)を設定することが非常に重要です。

また、メッセージキューはサブスクライバーがオフラインの間に到着したメッセージ(QoS 0 メッセージを含む)を保存し、サブスクライバーが次回オンラインになった際に送信するためにも使用されます。QoS 0 メッセージは重要度が低い場合があるため、EMQX が QoS 0 メッセージをキューに保存する機能を無効にすることも可能です。詳細は mqueue_store_qos0 をご参照ください。

なお、Inflight Window とメッセージキューはグローバルではなく、EMQX は各クライアント接続ごとに個別の Inflight Window とメッセージキューを割り当てます。

Inflight Window と Receive Maximum

MQTT v5 プロトコルは CONNECT パケットに Receive Maximum 属性を追加しており、その公式説明は以下の通りです。

クライアントは、この値を使用して、同時に処理可能な QoS 1 および QoS 2 のパブリッシュメッセージの最大数を制限します。サーバーが送信しようとする QoS 0 のパブリッシュメッセージを制限する仕組みはありません。

つまり、サーバーはアックを待つ間に異なるメッセージ識別子を持つ PUBLISH パケットをクライアントに連続して送信できますが、未アックのメッセージ数が Receive Maximum の制限に達すると送信を停止します。

このことから、Receive Maximum は実質的に EMQX の Inflight Window 機構と同じであることがわかります。ただし、EMQX は MQTT v5.0 プロトコルがリリースされる前からこの機能を MQTT クライアントに提供していました。現在、MQTT v5.0 プロトコルを使用するクライアントは Receive Maximum の仕様に従って Inflight Window の最大長を設定し、以前のバージョンの MQTT プロトコルを使用するクライアントは設定に基づいて設定されます。

ただし、EMQX は CONNECT パケットで要求された Receive Maximum の値を必ずしも許可するわけではありません。代わりに、CONNACK パケットで許可される Receive Maximummqtt.max_inflight 設定によって上限が決まります。

設定項目

設定項目オプション値デフォルト値説明
mqtt.max_inflightinteger(0, 65536)32Inflight Window の長さ制限。0 は無制限を意味します
mqtt.max_mqueue_leninteger[0, ∞)1000メッセージキューの長さ制限。0 は無制限を意味します
mqtt.mqueue_store_qos0enumtrue, falsetrueクライアントがオフライン時に EMQX が QoS 0 メッセージをメッセージキューに保存するかどうか