# インフライトおよびメッセージキュー

## はじめに

メッセージのスループットを向上させ、ネットワークの変動による影響を軽減するために、EMQXは複数の未アック済みのQoS 1およびQoS 2メッセージを同時にインフライト状態に保つことができます。送信済みで未確認のメッセージは、アックが完了するまでインフライトウィンドウに格納されます。

インフライトメッセージの数が制限値、すなわちインフライトウィンドウの長さ制限（`max_inflight`参照）を超えた場合、EMQXはそれ以上のメッセージを送信せず、これらのメッセージをメッセージキューに格納します。インフライトウィンドウ内のメッセージがアックされると、メッセージキュー内のメッセージが先入れ先出し（FIFO）順に送信され、インフライトウィンドウに格納されます。

QoS 1およびQoS 2のインフライトメッセージ数がインフライトウィンドウの最大制限（`max_inflight`参照）に達すると、新たに到着したメッセージは即座に転送されず、一時的にメッセージキューに保存されます。

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

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

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

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

## インフライトウィンドウとReceive Maximum

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

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

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

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

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

## 設定項目

| 設定項目               | 型       | オプション値       | デフォルト値 | 説明                                                             |
| ---------------------- | -------- | ------------------ | ------------ | ---------------------------------------------------------------- |
| mqtt.max_inflight      | integer  | (0, 65536)         | 32           | インフライトウィンドウの長さ制限。0は無制限を意味します          |
| mqtt.max_mqueue_len    | integer  | [0, ∞)             | 1000         | メッセージキューの長さ制限。0は無制限を意味します                |
| mqtt.mqueue_store_qos0 | enum     | `true`, `false`    | true         | クライアントがオフライン時にEMQXがQoS 0メッセージをメッセージキューに保存するかどうか |
