[17] HTTP/2接続では複数のストリームを含めることができ、 複数のデータを多重化して並行に送受信することができます。 しかし受信者のメモリーなどの資源は有限ですから、 HTTP やアプリケーションの処理能力を超えない配慮が必要となります。 フロー制御は、資源の制約があるエンドポイントを保護するためのものです >>1。
[5] HTTP/2 のフロー制御は、具体的なアルゴリズムは規定せず送受信者とフレームが満たすべき要件のみを規定しています。 プロトコルを変更せずに適切なフロー制御アルゴリズムを実装できます >>1。
[3] フロー制御は、接続全体に関するものと、その中の個別のストリームに関するもので 2段階で行われます >>1, >>23。
[6] フロー制御は特定の接続について制御するもので、
単一のホップ (エンドポイント間) に適用されます >>1, >>23。
利用者エージェントから起源サーバーまでの全体に適用されるものではありません。
中間器は、 WINDOW_UPDATE
フレームを転送しません >>23。
(もちろん、間接的に影響を及ぼすことはあります >>23。)
[4] フロー制御には、 WINDOW_UPDATE
フレームを使います。
受信者は、ストリームについて、および接続全体について、
受信できるバイト数を広告します。これは credit に基づく方式です。
>>1
[11] しかし WINDOW_UPDATE
フレームをいつ送信するか、
どのように値を決めるか、送信者が送信するかどう判断するかを HTTP/2
仕様としては規定していません。実装は適切なアルゴリズムを実装することができます。
>>1
[8] 新しいストリームおよび接続全体のフロー制御窓の初期値は、 65535 バイトです。 >>1
[7] フロー制御は受信者によって制御されます。 受信者はストリームについて、また接続全体について、 任意の窓サイズを設定することができます。 送信者は、受信者によるフロー制御上の制限に従わなければなりません。 >>1
[14] フロー制御が必要ない受信者は、データを受信する度に最大の 231-1 のフロー制御窓を広告することにより、 実質的にフロー制御を無効化できます。 >>1
[9] フロー制御が適用されるかどうかは、フレーム型に依存します。
フロー制御対象のフレームは、 DATA
フレームのみです。 >>1, >>23
従って重要な制御フレームがフロー制御によりブロックされることはありません >>1。
[16] 帯域遅延積がわからない状態でフロー制御を行うと、
ネットワーク資源を十分使い切れないかもしれません。しかし帯域遅延積がわかっていたとしても、
フロー制御は難しいです。受信者は、 TCP 受信バッファーからデータを随時読み込まなければなりません。
そうしなければ、 WINDOW_UPDATE
など重要なフレームを読んで処理することができず、
デッドロックに陥る虞があります。 >>1
[15] 送信者は、常に受信者が広告したフロー制御窓に従う必要があります。 >>1 送信者は、受信者が広告した接続フロー制御窓とストリームフロー制御窓のいずれかを超える長さのフロー制御対象のフレームを送信してはなりません >>23。 ストリームフロー制御窓の値が負の時も、送信してはなりません >>23。
[40] 送信者は、 END_STREAM
フラグが設定され長さが 0 のフレームなら、
フロー制御窓に空きがなくても送信して構いません >>23。
[41] 送信者は、フロー制御対象のフレームを送信したら、 接続フロー制御窓とストリームフロー制御窓から送信したフレームの payload の長さ分を減らします >>23。
[25] フロー制御の適用対象でないフレーム型のフレームは、 フロー制御の状態に関わらず受け入れて処理しなければなりません >>23。
[26] フロー制御によりフレームを受け入れられないのにフレームを受信したら、
ストリームエラーまたは接続エラー FLOW_CONTROL_ERROR
として構いません >>23。
[36] フロー制御対象のフレームを受信したら、 これを接続エラーとして扱う場合を除き、 (エラーである場合も含めて) その接続フロー制御窓への貢献を勘案しなければなりません >>23。
[69] closed 状態のストリームで DATA
フレームを受信した場合でも、接続フロー制御窓には数えます >>64。
[71] GOAWAY
フレームの送信後で無視するストリームの
DATA
フレームを受信した場合、
接続フロー制御窓には数えなければなりません >>70。
[42] フロー制御対象のフレームの受信者は、データを消費してフロー制御窓の領域が解放される度に、
WINDOW_UPDATE
フレームを送信します。ストリームフロー制御窓と接続フロー制御窓について別々に送信します。
>>23
[38] 送信者は、窓 (フロー制御窓) を持ちます。 フロー制御窓には、接続全体の接続フロー制御窓と、 ストリーム毎のストリームフロー制御窓があります。 フロー制御窓は、単純な整数値で、送信者が転送できるデータのバイト数です。 これは受信者のバッファリング能力を表しています。 >>23
[39] フロー制御の計算では、フレームのヘッダーは数えません >>23。 payload の長さのみが対象となります。詰めは対象になります。
[49] フロー制御窓のサイズの初期値は、 65535 バイトです >>23。
[50] 接続の確立時に、接続フロー制御窓は初期値に設定されます >>23。
[52] ストリームの生成時に、ストリームフロー制御窓は初期値に設定されます >>23。
[46] SETTINGS
フレームの
SETTINGS_INITIAL_WINDOW_SIZE
設定で、
初期値が変更されます >>23。
[47] 初期値の設定が変更されると、既存のストリームのストリームフロー制御窓もその差分に応じて調整しなければなりません >>23。 その結果値が負になることもあります >>23。
[54] フロー制御対象フレームの受信者が現在より小さなフロー制御窓を使いたい時は、
SETTINGS
フレームを送信できます。しかし、
その処理前に既にデータが送られている場合がありますから、
受信者は新しいフロー制御窓サイズより大きなデータを受信する準備をしなければなりません。
受信者は SETTINGS
フレームを削減した後も、
フロー制御の限界を超えたストリームの処理を継続して構いません。
その場合フロー制御窓に割り当てた領域を直ちに開放することはできません。
WINDOW_UPDATE
フレームを送らない限り送信者が送信を再開しないため、
処理が止まってしまう可能性もあります。誤り符号 FLOW_CONTROL_ERROR
の RST_STREAM
フレームを送信することにしても構いません。 >>23
[61] フロー制御窓の管理方法は、fingerprinting vector です >>60。
WINDOW_UPDATE
フレーム[32] ストリーム識別子は、特定のストリーム識別子を指定することもできますし、
0x0
により接続全体を表すこともできます >>23。
[30] フラグはありません >>23。 0 でなければなりません >>63。 受信者は無視しなければなりません >>63。
[34] WINDOW_UPDATE
フレームは、 END_STREAM
フラグの設定されたフレームを送信したエンドポイントが送信できます。
(つまり half-closed (remote) や closed のストリームで受信する可能性があります。)
>>23
[66] reserved (remote)、open、half-closed (local) で送信できます。
[35] 受信者は、 half-closed (remote) や closed で
WINDOW_UPDATE
フレームを受信しても、
エラーとしてはなりません >>23。
[65] half-closed (local) でも受信するかもしれません >>64。
[33] 受信者は、フロー制御窓の増分が 0 なら、
ストリームエラー (接続全体に対するものなら接続エラー)
PROTOCOL_ERROR
としなければなりません >>23。
[37] payload の長さが 4 以外なら、接続エラー FRAME_SIZE_ERROR
としなければなりません >>23。
[44] フロー制御対象のフレームの送信者は、
フロー制御窓が 231-1 を超えることを認めてはなりません。
そのように求める WINDOW_UPDATE
フレームを受信したら、
接続またはストリームを閉じなければなりません。
FLOW_CONTROL_ERROR
誤り符号を使って
GOAWAY
フレームか RST_STREAM
フレームを送信します。
>>23
PROTOCOL_ERROR
を送信します。
ストリームについてはストリームエラー FLOW_CONTROL_ERROR
を送信します。Firefox はどちらも仕様通りです。 [43] WINDOW_UPDATE
フレームを受信したら、
フロー制御窓を指定に従い更新します >>23。
[58] WINDOW_UPDATE
フレームは、無駄な処理をさせるために濫用できます。
エンドポイントは利用状況を監視して制限するべきです。
接続エラー ENHANCE_YOUR_CALM
としても構いません。 >>59
[19] 設定 SETTINGS_INITIAL_WINDOW_SIZE
(0x4
) は、
送信者のストリームレベルのフロー制御の初期窓サイズをバイト単位で表します >>18。
[22] 最大フロー制御窓サイズである 231-1 より大きな値は、
接続エラー FLOW_CONTROL_ERROR
としなければなりません
>>18。
[53] いずれかのフロー制御窓の値が最大サイズを超えるように
SETTINGS_INITIAL_WINDOW_SIZE
を変更しようとした場合は、
接続エラー FLOW_CONTROL_ERROR
としなければなりません >>23。
FLOW_CONTROL_ERROR
[57] 誤り符号 FLOW_CONTROL_ERROR
(0x3
)
は、 peer がフロー制御プロトコルに違反していることを示します >>56。
[75] 具体的な動作はプラットフォームやメモリー利用状況などで異なるかもしれません。
[72] Chrome は接続序文の SETTINGS
で、
SETTINGS_INITIAL_WINDOW_SIZE
を 10485760 = 223 + 221
に設定します。
[73] Chrome は接続序文直後に
WINDOW_UPDATE
で値 10420225 = 223 + 221 - (216 - 1) を送信するようです。
[82] Chrome は一定量の (窓をかなり使うくらいの) DATA
を受信するごとに、そのストリームについての WINDOW_UPDATE
で
3153920 = 221 + 220 + 213 を送るようです。
[83] Chrome はそれに加えて (より少ない頻度で) 接続についての WINDOW_UPDATE
で 7872512 = 222 + 221 + 220 + 219 + 213
を送るようです。
[74] Firefox は接続序文の SETTINGS
で、
SETTINGS_INITIAL_WINDOW_SIZE
を 131072 = 216 × 2
に設定します。
[76] Firefox は接続序文直後に WINDOW_UPDATE
で値 268369921 = 228 - (216 - 1) を送信するようです。
[77] Firefox は HEADERS
の直後に、そのストリームについて
WINDOW_UPDATE
で値 268304384 = 228 - 216 × 2
を送信するようです。
[81] Firefox は一定量の (窓をかなり使うくらいの) DATA
を受信するごとに、
そのストリームについての WINDOW_UPDATE
と、
接続についての WINDOW_UPDATE
でそれぞれ
4194304 = 222 ずつ増やすようです。
[88] #959 (Permit post before acking settings) – nginx ( ()) https://trac.nginx.org/nginx/ticket/959
[89] ios - NSURLErrorDomain Code=-1004 for few seconds after app start up - Stack Overflow ( ()) http://stackoverflow.com/questions/36907767/nsurlerrordomain-code-1004-for-few-seconds-after-app-start-up