メインコンテンツまでスキップ

5. Streams and Multiplexing (ストリームと多重化)

「ストリーム (stream)」は、HTTP/2接続内でクライアントとサーバーの間で交換されるフレームの独立した双方向シーケンスです。ストリームにはいくつかの重要な特徴があります:

  • 単一のHTTP/2接続は、複数の同時に開いているストリームを含むことができ、いずれのエンドポイントも複数のストリームからフレームを交互に送信できます。

  • ストリームは、クライアントまたはサーバーのいずれかによって一方的に確立および使用されるか、共有されます。

  • ストリームは、いずれのエンドポイントによっても閉じることができます。

  • ストリーム上でフレームが送信される順序は重要です。受信者は、受信した順序でフレームを処理します。特に、HEADERSフレームとDATAフレームの順序は意味的に重要です。

  • ストリームは整数によって識別されます。ストリーム識別子は、ストリームを開始するエンドポイントによってストリームに割り当てられます。

5.1. Stream States (ストリーム状態)

ストリームのライフサイクルは図2に示されています。

                             +--------+
send PP | | recv PP
,--------+ idle +--------.
/ | | \
v +--------+ v
+----------+ | +----------+
| | | send H / | |
,-----+ reserved | | recv H | reserved +-----.
| | (local) | | | (remote) | |
| +---+------+ v +------+---+ |
| | +--------+ | |
| | recv ES | | send ES | |
| send H | ,-------+ open +-------. | recv H |
| | / | | \ | |
| v v +---+----+ v v |
| +----------+ | +----------+ |
| | half- | | | half- | |
| | closed | | send R / | closed | |
| | (remote) | | recv R | (local) | |
| +----+-----+ | +-----+----+ |
| | | | |
| | send ES / | recv ES / | |
| | send R / v send R / | |
| | recv R +--------+ recv R | |
| send R / `----------->| |<-----------' send R / |
| recv R | closed | recv R |
`----------------------->| |<----------------------'
+--------+

send: エンドポイントがこのフレームを送信
recv: エンドポイントがこのフレームを受信

H: HEADERSフレーム (暗黙的なCONTINUATIONフレームを含む)
PP: PUSH_PROMISEフレーム (暗黙的なCONTINUATIONフレームを含む)
ES: END_STREAMフラグ
R: RST_STREAMフレーム

図2: ストリーム状態

この図は、ストリーム状態の遷移と、それらの状態変更に影響を与えるフレームおよびフラグのみを示していることに注意してください。この点で、CONTINUATIONフレームは状態遷移をもたらさず、それらが続くHEADERSまたはPUSH_PROMISEの一部です。状態遷移の目的では、END_STREAMフラグは、それを保持するフレームとは別のイベントとして処理されます。END_STREAMフラグが設定されたHEADERSフレームは、2つの状態遷移を引き起こす可能性があります。

両方のエンドポイントは、フレームが転送中の場合に異なる可能性があるストリームの状態の主観的なビューを持っています。エンドポイントはストリームの作成を調整しません。それらは、いずれかのエンドポイントによって一方的に作成されます。状態の不一致の悪影響は、RST_STREAMを送信した後の「closed」状態に限定され、閉じた後しばらくの間フレームが受信される可能性があります。

ストリームには以下の状態があります:

idle (アイドル): すべてのストリームは「idle」状態から始まります。

この状態から有効な遷移は次のとおりです:

  • HEADERSフレームの送信または受信により、ストリームは「open」になります。ストリーム識別子は、セクション5.1.1で説明されているように選択されます。同じHEADERSフレームにより、ストリームが即座に「half-closed」になることもあります。

  • 別のストリーム上でPUSH_PROMISEフレームを送信すると、後で使用するために識別されたアイドルストリームが予約されます。予約されたストリームのストリーム状態は「reserved (local)」に遷移します。

  • 別のストリーム上でPUSH_PROMISEフレームを受信すると、後で使用するために識別されたアイドルストリームが予約されます。予約されたストリームのストリーム状態は「reserved (remote)」に遷移します。

  • PUSH_PROMISEフレームはアイドルストリーム上で送信されるのではなく、Promised Stream IDフィールドで新しく予約されたストリームを参照することに注意してください。

この状態のストリーム上でHEADERSまたはPRIORITY以外のフレームを受信することは、タイプPROTOCOL_ERRORの接続エラー (セクション5.4.1) として扱わなければなりません (MUST)。

reserved (local) (予約 (ローカル)): 「reserved (local)」状態のストリームは、PUSH_PROMISEフレームを送信することによって約束されたストリームです。PUSH_PROMISEフレームは、リモートピアによって開始されたオープンストリームとストリームを関連付けることによって、アイドルストリームを予約します (セクション8.4を参照)。

この状態では、次の遷移のみが可能です:

  • エンドポイントはHEADERSフレームを送信できます。これにより、ストリームは「half-closed (remote)」状態で開きます。

  • いずれかのエンドポイントがRST_STREAMフレームを送信して、ストリームを「closed」にすることができます。これにより、ストリーム予約が解放されます。

エンドポイントは、この状態でHEADERS、RST_STREAM、またはPRIORITY以外のタイプのフレームを送信してはなりません (MUST NOT)。

この状態ではPRIORITYまたはWINDOW_UPDATEフレームを受信する場合があります (MAY)。この状態のストリーム上でRST_STREAM、PRIORITY、またはWINDOW_UPDATE以外のタイプのフレームを受信することは、タイプPROTOCOL_ERRORの接続エラー (セクション5.4.1) として扱わなければなりません (MUST)。

reserved (remote) (予約 (リモート)): 「reserved (remote)」状態のストリームは、リモートピアによって予約されています。

この状態では、次の遷移のみが可能です:

  • HEADERSフレームを受信すると、ストリームは「half-closed (local)」に遷移します。

  • いずれかのエンドポイントがRST_STREAMフレームを送信して、ストリームを「closed」にすることができます。これにより、ストリーム予約が解放されます。

エンドポイントは、この状態で予約されたストリームの優先順位を変更するためにPRIORITYフレームを送信できます (MAY)。エンドポイントは、この状態でRST_STREAM、WINDOW_UPDATE、またはPRIORITY以外のタイプのフレームを送信してはなりません (MUST NOT)。

この状態のストリーム上でHEADERS、RST_STREAM、またはPRIORITY以外のタイプのフレームを受信することは、タイプPROTOCOL_ERRORの接続エラー (セクション5.4.1) として扱わなければなりません (MUST)。

open (オープン): 「open」状態のストリームは、両方のピアが任意のタイプのフレームを送信するために使用できます。この状態では、送信ピアは通知されたストリームレベルのフロー制御制限 (セクション5.2) を遵守します。

この状態から、いずれかのエンドポイントがEND_STREAMフラグが設定されたフレームを送信でき、ストリームは「half-closed」状態の1つに遷移します。END_STREAMフラグを送信するエンドポイントは、ストリーム状態を「half-closed (local)」にします。END_STREAMフラグを受信するエンドポイントは、ストリーム状態を「half-closed (remote)」にします。

いずれかのエンドポイントがこの状態からRST_STREAMフレームを送信でき、即座に「closed」に遷移します。

half-closed (local) (半閉鎖 (ローカル)): 「half-closed (local)」状態のストリームは、WINDOW_UPDATE、PRIORITY、およびRST_STREAM以外のフレームの送信には使用できません。

ストリームは、END_STREAMフラグが設定されたフレームが受信されたとき、またはいずれかのピアがRST_STREAMフレームを送信したときに、この状態から「closed」に遷移します。

エンドポイントは、この状態で任意のタイプのフレームを受信できます。WINDOW_UPDATEフレームを使用してフロー制御クレジットを提供することは、フロー制御されたフレームを受信し続けるために必要です。この状態では、受信者は、END_STREAMフラグが設定されたフレームが送信された後、短期間到着する可能性のあるWINDOW_UPDATEフレームを無視できます。

この状態で受信されたPRIORITYフレームは、識別されたストリームに依存するストリームの優先順位を変更するために使用されます。

half-closed (remote) (半閉鎖 (リモート)): 「half-closed (remote)」であるストリームは、ピアがフレームを送信するために使用されなくなります。この状態では、エンドポイントは受信者フロー制御ウィンドウを維持する義務がなくなります。

エンドポイントがこの状態のストリームに対して、WINDOW_UPDATE、PRIORITY、またはRST_STREAM以外の追加のフレームを受信した場合、タイプSTREAM_CLOSEDのストリームエラー (セクション5.4.2) で応答しなければなりません (MUST)。

「half-closed (remote)」であるストリームは、エンドポイントが任意のタイプのフレームを送信するために使用できます。この状態では、エンドポイントは通知されたストリームレベルのフロー制御制限 (セクション5.2) を遵守し続けます。

ストリームは、END_STREAMフラグが設定されたフレームを送信することによって、またはいずれかのピアがRST_STREAMフレームを送信したときに、この状態から「closed」に遷移できます。

closed (閉鎖): 「closed」状態は終端状態です。

エンドポイントは、閉じられたストリーム上でPRIORITY以外のフレームを送信してはなりません (MUST NOT)。RST_STREAMを受信した後にPRIORITY以外のフレームを受信したエンドポイントは、それをタイプSTREAM_CLOSEDのストリームエラー (セクション5.4.2) として扱わなければなりません (MUST)。同様に、END_STREAMフラグが設定されたフレームを受信した後に任意のフレームを受信したエンドポイントは、以下で説明されているようにフレームが許可されていない限り、それをタイプSTREAM_CLOSEDの接続エラー (セクション5.4.1) として扱わなければなりません (MUST)。

END_STREAMフラグを含むDATAまたはHEADERSフレームが送信された後、短期間この状態でWINDOW_UPDATEまたはRST_STREAMフレームを受信する可能性があります。リモートピアがRST_STREAMまたはEND_STREAMフラグを含むフレームを受信して処理するまで、これらのタイプのフレームを送信する可能性があります。エンドポイントは、この状態で受信されたWINDOW_UPDATEまたはRST_STREAMフレームを無視しなければなりません (MUST)。ただし、エンドポイントは、END_STREAMを送信してからかなり後に到着したフレームをタイプPROTOCOL_ERRORの接続エラー (セクション5.4.1) として扱うことを選択できます (MAY)。

PRIORITYフレームは、閉じられたストリームに依存するストリームの優先順位を付けるために、閉じられたストリーム上で送信できます。エンドポイントはPRIORITYフレームを処理すべきですが (SHOULD)、ストリームが依存関係ツリーから削除されている場合は無視できます ([RFC7540]のセクション5.3.3を参照)。

この状態がRST_STREAMフレームを送信した結果として到達した場合、RST_STREAMを受信するピアは、取り消すことができないストリーム上のフレームをすでに送信した、または送信のためにキューに入れた可能性があります。エンドポイントは、RST_STREAMフレームを送信した後に閉じられたストリーム上で受信するフレームを無視しなければなりません (MUST)。エンドポイントは、フレームを無視する期間を制限し、この時間後に到着するフレームをエラーとして扱うことを選択できます (MAY)。

RST_STREAMを送信した後に受信されたフロー制御されたフレーム (すなわち、DATA) は、接続フロー制御ウィンドウに対してカウントされます。これらのフレームは無視される可能性がありますが、送信者がRST_STREAMを受信する前に送信されるため、送信者はフレームがフロー制御ウィンドウに対してカウントされると見なします。

エンドポイントは、RST_STREAMを送信した後にPUSH_PROMISEフレームを受信する可能性があります。PUSH_PROMISEは、関連するストリームがリセットされている場合でも、ストリームを「reserved」にします。したがって、不要な約束されたストリームを閉じるにはRST_STREAMが必要です。

より具体的なルールがない場合、実装は、状態の説明で明示的に許可されていないフレームの受信を、タイプPROTOCOL_ERRORの接続エラー (セクション5.4.1) として扱うべきです (SHOULD)。PRIORITYは任意のストリーム状態で送受信できることに注意してください。

このセクションのルールは、このドキュメントで定義されたフレームにのみ適用されます。セマンティクスが不明なフレームの受信はエラーとして扱うことはできません。それらのフレームを送受信する条件も不明であるためです。セクション5.5を参照してください。

HTTPリクエスト/レスポンス交換の状態遷移の例は、セクション8.8にあります。サーバープッシュの状態遷移の例は、セクション8.4.1および8.4.2にあります。

5.1.1. Stream Identifiers (ストリーム識別子)

ストリームは、符号なし31ビット整数によって識別されます。クライアントによって開始されたストリームは、奇数のストリーム識別子を使用しなければなりません (MUST)。サーバーによって開始されたストリームは、偶数のストリーム識別子を使用しなければなりません (MUST)。ゼロ (0x00) のストリーム識別子は、接続制御メッセージに使用されます。ゼロのストリーム識別子は、新しいストリームを確立するために使用できません。

新しく確立されたストリームの識別子は、開始エンドポイントが開いたまたは予約したすべてのストリームよりも数値的に大きくなければなりません (MUST)。これは、HEADERSフレームを使用して開かれたストリームと、PUSH_PROMISEを使用して予約されたストリームを管理します。予期しないストリーム識別子を受信したエンドポイントは、タイプPROTOCOL_ERRORの接続エラー (セクション5.4.1) で応答しなければなりません (MUST)。

HEADERSフレームは、フレームヘッダーのストリーム識別子によって識別されるクライアント開始ストリームを「idle」から「open」に遷移させます。PUSH_PROMISEフレームは、フレームペイロードのPromised Stream IDフィールドによって識別されるサーバー開始ストリームを「idle」から「reserved (local)」または「reserved (remote)」に遷移させます。ストリームが「idle」状態から遷移すると、より小さい値のストリーム識別子でピアによって開かれた可能性のある「idle」状態のすべてのストリームが即座に「closed」に遷移します。つまり、エンドポイントはストリーム識別子をスキップでき、その効果はスキップされたストリームが即座に閉じられることです。

ストリーム識別子は再利用できません。長時間存在する接続により、エンドポイントが利用可能なストリーム識別子の範囲を使い果たす可能性があります。新しいストリーム識別子を確立できないクライアントは、新しいストリームのために新しい接続を確立できます。新しいストリーム識別子を確立できないサーバーは、GOAWAYフレームを送信して、クライアントが新しいストリームのために新しい接続を開くことを強制できます。

5.1.2. Stream Concurrency (ストリーム並行性)

ピアは、SETTINGSフレーム内のSETTINGS_MAX_CONCURRENT_STREAMSパラメーター (セクション6.5.2を参照) を使用して、同時にアクティブなストリームの数を制限できます。最大同時ストリーム設定は各エンドポイントに固有であり、設定を受信するピアにのみ適用されます。つまり、クライアントはサーバーが開始できる最大同時ストリーム数を指定し、サーバーはクライアントが開始できる最大同時ストリーム数を指定します。

「open」状態または「half-closed」状態のいずれかにあるストリームは、エンドポイントが開くことが許可されている最大ストリーム数に対してカウントされます。これらの3つの状態のいずれかにあるストリームは、SETTINGS_MAX_CONCURRENT_STREAMS設定で通知された制限に対してカウントされます。「reserved」状態のいずれかのストリームは、ストリーム制限に対してカウントされません。

エンドポイントは、ピアによって設定された制限を超えてはなりません (MUST NOT)。通知された同時ストリーム制限を超えるHEADERSフレームを受信したエンドポイントは、これをタイプPROTOCOL_ERRORまたはREFUSED_STREAMのストリームエラー (セクション5.4.2) として扱わなければなりません (MUST)。エラーコードの選択により、エンドポイントが自動再試行を有効にしたいかどうかが決まります (詳細についてはセクション8.7を参照)。

SETTINGS_MAX_CONCURRENT_STREAMSの値を現在開いているストリーム数よりも低い値に減らしたいエンドポイントは、新しい値を超えるストリームを閉じるか、ストリームが完了するのを許可できます。

5.2. Flow Control (フロー制御)

多重化にストリームを使用すると、TCP接続の使用をめぐる競合が発生し、ストリームがブロックされます。フロー制御スキームは、同じ接続上のストリームが破壊的に相互に干渉しないことを保証します。フロー制御は、個々のストリームと接続全体の両方に使用されます。

HTTP/2は、WINDOW_UPDATEフレーム (セクション6.9) の使用を通じてフロー制御を提供します。

5.2.1. Flow-Control Principles (フロー制御の原則)

HTTP/2ストリームフロー制御は、プロトコルの変更を必要とせずに、さまざまなフロー制御アルゴリズムを使用できるようにすることを目的としています。HTTP/2のフロー制御には、次の特性があります:

  1. フロー制御は接続に固有です。HTTP/2フロー制御は、エンドツーエンドパス全体ではなく、単一ホップのエンドポイント間で動作します。

  2. フロー制御はWINDOW_UPDATEフレームに基づいています。受信者は、ストリーム上および接続全体で受信する準備ができているオクテット数を通知します。これはクレジットベースのスキームです。

  3. フロー制御は方向性があり、全体的な制御は受信者によって提供されます。受信者は、各ストリームおよび接続全体に対して任意のウィンドウサイズを設定することを選択できます (MAY)。送信者は、受信者によって課されたフロー制御制限を尊重しなければなりません (MUST)。クライアント、サーバー、および仲介者はすべて、受信者としてフロー制御ウィンドウを独立して通知し、送信時にピアによって設定されたフロー制御制限を遵守します。

  4. 新しいストリームと接続全体の両方に対するフロー制御ウィンドウの初期値は、65,535オクテットです。

  5. フレームタイプは、フロー制御がフレームに適用されるかどうかを決定します。このドキュメントで指定されているフレームのうち、DATAフレームのみがフロー制御の対象です。他のすべてのフレームタイプは、通知されたフロー制御ウィンドウのスペースを消費しません。これにより、重要な制御フレームがフロー制御によってブロックされないことが保証されます。

  6. エンドポイントは、自身のフロー制御を無効にすることを選択できますが、エンドポイントはピアからのフロー制御信号を無視することはできません。

  7. HTTP/2は、WINDOW_UPDATEフレームの形式とセマンティクスのみを定義します (セクション6.9)。このドキュメントは、受信者がこのフレームを送信するタイミングまたは送信する値を規定しておらず、送信者がパケットを送信する方法も指定していません。実装は、ニーズに合った任意のアルゴリズムを選択できます。

実装は、リクエストとレスポンスの送信の優先順位付け、リクエストのヘッドオブラインブロッキングを回避する方法の選択、および新しいストリームの作成の管理も担当します。これらのアルゴリズムの選択は、任意のフロー制御アルゴリズムと相互作用する可能性があります。

5.2.2. Appropriate Use of Flow Control (フロー制御の適切な使用)

フロー制御は、リソース制約の下で動作しているエンドポイントを保護するために定義されています。たとえば、プロキシは多くの接続間でメモリを共有する必要があり、また遅い上流接続と高速な下流接続を持つ可能性があります。フロー制御は、受信者が1つのストリーム上のデータを処理できないが、同じ接続上の他のストリームの処理を継続したい場合に対処します。

この機能を必要としないデプロイメントは、最大サイズ (2^31-1) のフロー制御ウィンドウを通知でき、任意のデータが受信されたときにWINDOW_UPDATEフレームを送信することによってこのウィンドウを維持できます。これにより、その受信者のフロー制御が効果的に無効になります。逆に、送信者は常に受信者によって通知されたフロー制御ウィンドウの制約を受けます。

制約されたリソース (たとえば、メモリ) を持つデプロイメントは、フロー制御を使用してピアが消費できるメモリ量を制限できます。ただし、帯域幅×遅延積 ([RFC7323]を参照) の知識なしにフロー制御が有効になっている場合、これは利用可能なネットワークリソースの次善の使用につながる可能性があることに注意してください。

現在の帯域幅×遅延積を完全に認識している場合でも、フロー制御の実装は困難な場合があります。エンドポイントは、データが利用可能になり次第、TCP受信バッファからHTTP/2フレームを読み取って処理しなければなりません (MUST)。迅速に読み取らないと、WINDOW_UPDATEなどの重要なフレームが読み取られて処理されない場合にデッドロックが発生する可能性があります。フレームを迅速に読み取ることは、HTTP/2フロー制御がリソースコミットメントを制限するため、エンドポイントをリソース枯渇攻撃にさらすことはありません。

5.2.3. Flow-Control Performance (フロー制御パフォーマンス)

エンドポイントが、ピアがこの接続のピアの帯域幅×遅延積よりも大きい利用可能なフロー制御ウィンドウスペースを常に持っていることを保証できない場合、その受信スループットはHTTP/2フロー制御によって制限されます。これにより、パフォーマンスが低下します。

タイムリーなWINDOW_UPDATEフレームの送信は、パフォーマンスを向上させることができます。エンドポイントは、受信スループットを向上させる必要性とリソース枯渇リスクを管理する必要性とのバランスをとることを望み、ウィンドウサイズを管理する戦略を定義する際にセクション10.5を注意深く確認する必要があります。

5.3. Prioritization (優先順位付け)

HTTP/2のような多重化プロトコルでは、ストリームへの帯域幅と計算リソースの割り当ての優先順位付けは、良好なパフォーマンスを達成するために重要です。不適切な優先順位付けスキームは、HTTP/2が不十分なパフォーマンスを提供する結果となる可能性があります。TCP層での並列処理がない場合、パフォーマンスはHTTP/1.1よりも大幅に悪化する可能性があります。

優れた優先順位付けスキームは、リソースの内容、リソースがどのように相互関連しているか、ピアがそれらのリソースをどのように使用するかなどのコンテキスト知識の適用から恩恵を受けます。特に、クライアントは、サーバーの優先順位付けに関連するリクエストの優先度に関する知識を持つことができます。これらの場合、クライアントに優先度情報を提供させることでパフォーマンスが向上する可能性があります。

5.3.1. Background on Priority in RFC 7540 (RFC 7540における優先度の背景)

RFC 7540は、リクエストの優先度を通知するための豊富なシステムを定義しました。しかし、このシステムは複雑であることが判明し、統一的に実装されていませんでした。

柔軟なスキームは、クライアントがまったく異なる方法で優先度を表現できることを意味し、採用されたアプローチの一貫性はほとんどありませんでした。サーバーの場合、スキームの汎用サポートを実装することは複雑でした。クライアントとサーバーの両方で優先度の実装は不均一でした。多くのサーバーデプロイメントは、リクエストの処理に優先順位を付けるときにクライアント信号を無視しました。

要するに、RFC 7540 [RFC7540] の優先順位通知は成功しませんでした。

5.3.2. Priority Signaling in This Document (このドキュメントでの優先度通知)

HTTP/2へのこの更新は、RFC 7540 [RFC7540] で定義された優先度通知を非推奨にします。優先度信号に関連するテキストの大部分は、このドキュメントに含まれていません。フレームフィールドの説明と一部の必須処理は、このドキュメントの実装が、RFC 7540で説明されている優先度通知を使用する実装と相互運用可能であることを保証するために保持されています。

RFC 7540優先度スキームの詳細な説明は、[RFC7540]のセクション5.3に残っています。

多くの場合、良好なパフォーマンスを達成するには、優先度情報を通知することが必要です。優先度情報を通知することが重要な場合、エンドポイントは、[HTTP-PRIORITY]で説明されているスキームなどの代替スキームを使用することをお勧めします。

RFC 7540の優先度通知は広く採用されていませんでしたが、より良い情報がない場合、それが提供する情報は依然として有用です。HEADERSまたはPRIORITYフレームで優先度信号を受信するエンドポイントは、その情報を適用することから恩恵を受けることができます。特に、これらの信号を消費する実装は、代替手段がない場合にこれらの優先度信号を破棄することから恩恵を受けません。

サーバーは、優先度信号がない場合、リクエストの優先度を決定する際に他のコンテキスト情報を使用すべきです (SHOULD)。サーバーは、信号が完全にないことを、クライアントが機能を実装していないことの指示として解釈できます (MAY)。[RFC7540]のセクション5.3.5で説明されているデフォルトは、ほとんどの条件下でパフォーマンスが悪いことが知られており、その使用は意図的である可能性は低いです。

5.4. Error Handling (エラー処理)

HTTP/2フレーミングは、2つのクラスのエラーを許可します:

  • 接続全体を使用不可能にするエラー条件は、接続エラー (connection error) です。

  • 個々のストリームでのエラーは、ストリームエラー (stream error) です。

エラーコードのリストは、セクション7に含まれています。

エンドポイントが複数のエラーを引き起こすフレームに遭遇する可能性があります。実装は処理中に複数のエラーを発見する場合がありますが (MAY)、結果として最大1つのストリームエラーと1つの接続エラーを報告すべきです (SHOULD)。

特定のストリームに対して報告された最初のストリームエラーは、そのストリーム上の他のエラーが報告されることを防ぎます。対照的に、プロトコルは複数のGOAWAYフレームを許可しますが、エンドポイントは、優雅なシャットダウン中にエラーが発生しない限り、1つのタイプの接続エラーのみを報告すべきです (SHOULD)。これが発生した場合、エンドポイントは、NO_ERRORを含む以前のGOAWAYに加えて、新しいエラーコードを含む追加のGOAWAYフレームを送信できます (MAY)。

エンドポイントが複数の異なるエラーを検出した場合、それらのエラーのいずれかを報告することを選択できます (MAY)。フレームが接続エラーを引き起こす場合、そのエラーを報告しなければなりません (MUST)。さらに、エンドポイントは、エラー条件を検出したときに適用可能な任意のエラーコードを使用できます (MAY)。汎用エラーコード (PROTOCOL_ERRORやINTERNAL_ERRORなど) は、常により具体的なエラーコードの代わりに使用できます。

5.4.1. Connection Error Handling (接続エラー処理)

接続エラーは、フレーム層のさらなる処理を妨げる、または任意の接続状態を破壊する任意のエラーです。

接続エラーに遭遇したエンドポイントは、最初に、ピアから正常に受信した最後のストリームのストリーム識別子を含むGOAWAYフレーム (セクション6.8) を送信すべきです (SHOULD)。GOAWAYフレームには、接続が終了する理由を示すエラーコード (セクション7) が含まれます。エラー条件のためにGOAWAYフレームを送信した後、エンドポイントはTCP接続を閉じなければなりません (MUST)。

GOAWAYが受信エンドポイントによって確実に受信されない可能性があります。接続エラーの場合、GOAWAYは、接続が終了されている理由についてピアと通信するためのベストエフォートの試みのみを提供します。

エンドポイントはいつでも接続を終了できます。特に、エンドポイントは、ストリームエラーを接続エラーとして扱うことを選択できます (MAY)。エンドポイントは、状況が許せば、接続を終了するときにGOAWAYフレームを送信すべきです (SHOULD)。

5.4.2. Stream Error Handling (ストリームエラー処理)

ストリームエラーは、他のストリームの処理に影響を与えない特定のストリームに関連するエラーです。

ストリームエラーを検出したエンドポイントは、エラーが発生したストリームのストリーム識別子を含むRST_STREAMフレーム (セクション6.4) を送信します。RST_STREAMフレームには、エラーのタイプを示すエラーコードが含まれます。

RST_STREAMは、エンドポイントがストリーム上で送信できる最後のフレームです。RST_STREAMフレームを送信するピアは、リモートピアによって送信された、または送信のためにキューに入れられた任意のフレームを受信する準備をしなければなりません (MUST)。これらのフレームは、フィールドセクション圧縮 (セクション4.3) またはフロー制御のために維持される状態など、接続状態を変更する場合を除き、無視できます。

通常、エンドポイントは任意のストリームに対して複数のRST_STREAMフレームを送信すべきではありません (SHOULD NOT)。ただし、エンドポイントは、1ラウンドトリップ時間以上後に閉じられたストリーム上でフレームを受信した場合、追加のRST_STREAMフレームを送信できます (MAY)。この動作は、不正な動作をする実装に対処するために許可されています。

ループを回避するために、エンドポイントは、RST_STREAMフレームに応答してRST_STREAMを送信してはなりません (MUST NOT)。

5.4.3. Connection Termination (接続終了)

ストリームが「open」または「half-closed」状態のままTCP接続が閉じられたりリセットされたりした場合、影響を受けるストリームは自動的に再試行できません (詳細についてはセクション8.7を参照)。

5.5. Extending HTTP/2 (HTTP/2の拡張)

HTTP/2はプロトコルの拡張を許可します。このセクションで説明されている制限内で、プロトコル拡張を使用して、追加のサービスを提供したり、プロトコルの任意の側面を変更したりできます。拡張は、単一のHTTP/2接続の範囲内でのみ有効です。

これは、このドキュメントで定義されているプロトコル要素に適用されます。これは、新しいメソッド、ステータスコード、またはフィールドの定義など、HTTPを拡張するための既存のオプションには影響しません ([HTTP]のセクション16を参照)。

拡張は、新しいフレームタイプ (セクション4.1)、新しい設定 (セクション6.5)、または新しいエラーコード (セクション7) を使用することが許可されています。これらの拡張ポイントを管理するためのレジストリは、[RFC7540]のセクション11で定義されています。

実装は、すべての拡張可能なプロトコル要素で不明またはサポートされていない値を無視しなければなりません (MUST)。実装は、不明またはサポートされていないタイプのフレームを破棄しなければなりません (MUST)。これは、これらの拡張ポイントのいずれかが、事前の取り決めや交渉なしに拡張によって安全に使用できることを意味します。ただし、フィールドブロック (セクション4.3) の途中に表示される拡張フレームは許可されません。これらは、タイプPROTOCOL_ERRORの接続エラー (セクション5.4.1) として扱わなければなりません (MUST)。

拡張は、このドキュメントで定義されているプロトコル要素または拡張メカニズムが定義されていない要素の変更を避けるべきです (SHOULD)。これには、フレームのレイアウトの変更、フレームがHTTPメッセージに構成される方法への追加または変更 (セクション8.1)、疑似ヘッダーフィールドの定義、または準拠エンドポイントが接続エラー (セクション5.4.1) として扱う可能性のある任意のプロトコル要素への変更が含まれます。

既存のプロトコル要素または状態を変更する拡張は、使用される前に交渉されなければなりません (MUST)。たとえば、HEADERSフレームのレイアウトを変更する拡張は、ピアがこれが受け入れ可能であるという肯定的な信号を与えるまで使用できません。この場合、改訂されたレイアウトがいつ有効になるかを調整することも必要になる可能性があります。たとえば、DATAフレーム以外のフレームをフロー制御として扱うには、両方のエンドポイントが理解する必要があるセマンティクスの変更が必要であるため、これは交渉を通じてのみ実行できます。

このドキュメントは、拡張の使用を交渉するための特定の方法を義務付けていませんが、その目的のために設定 (セクション6.5.2) を使用できることに注意しています。両方のピアが拡張を使用する意思を示す値を設定した場合、拡張を使用できます。拡張交渉に設定が使用される場合、初期値は、拡張が最初に無効になるように定義されなければなりません (MUST)。


第5章完了!