Inflight Window とメッセージキュー
EMQX は、メッセージのスループットを向上させ、ネットワークの変動による影響を軽減するために、Inflight Window とメッセージキューを使用します。EMQX はこれらの構造をクライアント接続ごとに個別に管理します。
- Inflight Window:送信済みでまだアック(ACK)が返ってきていない QoS 1 および QoS 2 メッセージを保持します。EMQX は複数のメッセージを同時にインフライト状態にできますが、その数は
max_inflightによって制限されます。MQTT 5.0 クライアントの場合、EMQX はクライアントが通知するReceive Maximumとmax_inflightのうち小さい方の値で、同時に未アックの QoS 1 および QoS 2 メッセージ数を制限します。 - メッセージキュー:インメモリセッションにおいて、すぐに配信できないメッセージをバッファリングします。インメモリセッションは EMQX ノードのメモリ上に状態を保持します。
メッセージがメッセージキューに入るケースは以下の通りです。
- クライアントが切断されセッションが残っている場合。クライアントが再接続すると、EMQX はキューにあるメッセージを配信します。
- QoS 1 および QoS 2 メッセージがインフライト容量や配信クォータを待っている場合。
- 接続が混雑している場合。
mqueue_store_qos0 が有効な場合、クライアントがオフラインの間や接続が混雑している場合、または配信順序を保持する必要がある場合に、QoS 0 メッセージもキューに入ることがあります。オフライン時に QoS 0 メッセージをバッファリングから除外したい場合は、false に設定してください。
メッセージキューの配信動作
EMQX は接続の混雑状況に応じて、メッセージキューの配信を異なる方法で処理します。
- 混雑していない接続では、Inflight Window が
max_inflightの制限に達すると、EMQX は追加の QoS 1 および QoS 2 の配信を一時停止します。インフライトの空きスロットができると配信を再開します。QoS 0 メッセージは Inflight Window に入らないため、先行する QoS 1 または QoS 2 メッセージがスロット待ちの間も、EMQX はキューにある QoS 0 メッセージの配信を継続できます。 - 混雑している接続では、利用可能なインフライトスロット数が、クライアントからのアックに応じて EMQX がデキューできるメッセージ数を QoS に関係なく制限します。混雑が解消するかインフライトスロットが増えると、キューにある配信を再開します。
EMQX は同じトピックかつ同じ QoS レベルのメッセージについては配信順序を保持しますが、異なる QoS レベル間での厳密な FIFO 順序は保証しません。トピック優先度が有効な場合、EMQX はトピック優先度に基づいてキュー内メッセージをスケジューリングします。現在の優先度キューに配信可能な QoS 0 メッセージがない場合、より低い優先度のキューに QoS 0 メッセージが残っていても、現在のデキュー処理は停止します。
メッセージキューが max_mqueue_len に達すると、EMQX は最も古い QoS 0 メッセージを追い出します。QoS 0 メッセージがない場合は、残っている最も古いメッセージを追い出します。トピック優先度が有効な場合、この制限と追い出しポリシーは各優先度キューごとに独立して適用されます。短期間に多くの QoS 0 メッセージがキューに入る場合、このポリシーは QoS 1 および QoS 2 メッセージの配信進行を維持するのに役立ちます。
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 Maximum は mqtt.max_inflight 設定によって上限がかけられます。
設定項目
| 設定項目 | タイプ | オプション値 | デフォルト値 | 説明 |
|---|---|---|---|---|
| mqtt.max_inflight | integer | [1, 65535] | 32 | EMQX が同時に配信可能な未アックの QoS 1 および QoS 2 メッセージの最大数。MQTT 5.0 クライアントでは、より小さい Receive Maximum が優先されます。 |
| mqtt.max_mqueue_len | integer | [0, ∞) | 1000 | インメモリセッションのメッセージキューに格納可能なメッセージの最大数。0 は無制限を意味します。 |
| mqtt.mqueue_store_qos0 | enum | true, false | true | クライアントが切断中または接続が混雑している間に、EMQX がインメモリセッションのメッセージキューに QoS 0 メッセージを格納するかどうか。配信順序を保持するために QoS 0 メッセージをキューに入れる場合もあります。 |