-
Notifications
You must be signed in to change notification settings - Fork 4
/
352.txt
167 lines (121 loc) · 8.51 KB
/
352.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
* 仕様書
[REFS[
- [1] '''[CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-5.2>'''
- [18] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.5.2>
- [23] '''[CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.9>'''
]REFS]
* フロー制御
[17] [[HTTP/2接続]]では複数の[[ストリーム]]を含めることができ、
複数のデータを[[多重化]]して[[並行]]に送受信することができます。
しかし[[受信者]]の[[メモリー]]などの[[資源]]は有限ですから、
[[HTTP]] や[[アプリケーション]]の処理能力を超えない配慮が必要となります。
[[フロー制御]]は、[[資源]]の制約がある[[エンドポイント]]を保護するためのものです [SRC[>>1]]。
[EG[
[2] [[接続]]内で過剰に[[ストリーム]]を使って[[多重化]]すると、
他の[[ストリーム]]の処理に干渉して処理しきれなくなるかもしれません [SRC[>>1]]。
]EG]
[EG[
[12] [[プロキシ]]は多くの[[接続]]で[[メモリー]]を共有する必要がありますし、
[[上流]]の[[接続]]が遅く[[下流]]の[[接続]]が速かったりすることもあります。 [SRC[>>1]]
]EG]
** 要件
[5] [[HTTP/2]] の[[フロー制御]]は、具体的なアルゴリズムは規定せず送受信者と[[フレーム]]が満たすべき要件のみを規定しています。
プロトコルを変更せずに適切な[[フロー制御]]アルゴリズムを実装できます [SRC[>>1]]。
[3] [[フロー制御]]は、[[接続]]全体に関するものと、そこ中の個別の[[ストリーム]]に関するもので
2段階で行われます [SRC[>>1, >>23]]。
;; [13] [[受信者]]がある[[ストリーム]]の処理はできないものの他の[[ストリーム]]は処理したい、
という場合にも対応できます [SRC[>>1]]。
[6] [[フロー制御]]は特定の[[接続]]について制御するもので、
単一の[[ホップ]] ([[エンドポイント]]間) に適用されます [SRC[>>1, >>23]]。
[[利用者エージェント]]から[[起源サーバー]]までの全体に適用されるものではありません。
[[中間器]]は、 [CODE[[[WINDOW_UPDATE]]]] [[フレーム]]を[[転送]]しません [SRC[>>23]]。
(もちろん、間接的に影響を及ぼすことはあります [SRC[>>23]]。)
[4] [[フロー制御]]には、 [CODE[[[WINDOW_UPDATE]]]] [[フレーム]]を使います。
[[受信者]]は、[[ストリーム]]について、および[[接続]]全体について、
受信できる[[バイト]]数を[[広告]]します。これは [RUBYB[credit に基づく方式]@en[credit-based scheme]]です。
[SRC[>>1]]
[11] しかし [CODE[[[WINDOW_UPDATE]]]] [[フレーム]]をいつ送信するか、
どのように値を決めるか、[[送信者]]が送信するかどう判断するかを [[HTTP/2]]
仕様としては規定していません。実装は適切な[[アルゴリズム]]を実装することができます。
[SRC[>>1]]
[8] 新しい[[ストリーム]]および[[接続]]全体の[[フロー制御窓]]の初期値は、
65535 [[バイト]]です。 [SRC[>>1]]
[7] [[フロー制御]]は[[受信者]]によって制御されます。
[[受信者]]は[[ストリーム]]について、また[[接続]]全体について、
任意の[[窓サイズ]]を設定することができます。
[[送信者]]は、[[受信者]]による[[フロー制御]]上の制限に従わなければ[['''なりません''']]。
[SRC[>>1]]
[10] [[フロー制御]]は、無効にはできません。 [SRC[>>1]]
[14] [[フロー制御]]が必要ない[[受信者]]は、データを受信する度に最大の
2[SUP[31]]-1 の[[フロー制御窓]]を[[広告]]することにより、
実質的に[[フロー制御]]を無効化できます。 [SRC[>>1]]
[15] [[送信者]]は、常に[[受信者]]が[[広告]]した[[フロー制御窓]]に従う必要があります。
[SRC[>>1]]
[9] [[フロー制御]]が適用されるかどうかは、[[フレーム型]]に依存します。
現時点で適用される対象は、 [CODE[[[DATA]]]] [[フレーム]]のみです。 [SRC[>>1, >>23]]
従って重要な制御フレームが[[フロー制御]]によりブロックされることはありません [SRC[>>1]]。
[16] [[帯域遅延積]]がわからない状態で[[フロー制御]]を行うと、
[[ネットワーク資源]]を十分使い切れないかもしれません。しかし[[帯域遅延積]]がわかっていたとしても、
[[フロー制御]]は難しいです。[[受信者]]は、 [[TCP]] [[受信バッファー]]からデータを随時読み込まなけれ[['''ばなりません''']]。
そうしなければ、 [CODE[[[WINDOW_UPDATE]]]] など重要な[[フレーム]]を読んで処理することができず、
[[デッドロック]]に陥る虞があります。 [SRC[>>1]]
** 処理
[25] [[フロー制御]]の適用対象でない[[フレーム型]]の[[フレーム]]は、
[[フロー制御]]の状態に関わらず受け入れて処理しなければ[['''なりません''']] [SRC[>>23]]。
[26] [[フロー制御]]により[[フレーム]]を受け入れられないのに[[フレーム]]を受信したら、
[[ストリームエラー]]または[[接続エラー]] [CODE[[[FLOW_CONTROL_ERROR]]]]
として構いません [SRC[>>23]]。
[36] [[フロー制御]]対象の[[フレーム]]を受信したら、
これを[[接続エラー]]として扱う場合を除き、
([[エラー]]である場合も含めて)
その[[接続フロー制御窓]]への貢献を勘案しなければ[['''なりません''']] [SRC[>>23]]。
* 意味
[24] [CODE[[[WINDOW_UPDATE]]]] [[フレーム]] ([[フレーム型]] [CODE[[[0x8]]]])
は、[[フロー制御]]の実装に使います [SRC[>>23]]。
* 構文
[32] [[ストリーム識別子]]は、特定の[[ストリーム識別子]]を指定することもできますし、
[CODE[[[0x0]]]] により[[接続]]全体を表すこともできます [SRC[>>23]]。
[30] [[フラグ]]はありません [SRC[>>23]]。
[FIG(packet)[
:width:8
= 1 0
= 1 0
= 1 0
= 1 0
= 1 0
= 1 0
= 1 0
= 1 0
]FIG]
[27] [[payload]] は次の欄で構成されます。
[28] R は、予約の1ビットのフラグです [SRC[>>23]]。
[29] [RUBYB[窓サイズ増分]@en[Window Size Increment]]は、
[[符号無し]]31ビット[[整数]] ([[ネットワークバイト順]]) の欄で、既存の[[フロー制御窓]]に加えて[[送信者]]が転送できる[[バイト]]数を表します [SRC[>>23]]。
[[合法]]な範囲は、 1 から 2[SUP[31]]-1 です [SRC[>>23]]。
[FIG(packet)[
:width:32
= 1 R
= 31 窓サイズ増分
]FIG]
* 文脈
[34] [CODE[[[WINDOW_UPDATE]]]] [[フレーム]]は、 [CODE[[[END_STREAM]]]]
[[フラグ]]の設定された[[フレーム]]を送信した[[エンドポイント]]が送信できます。
(つまり [[half-closed (remote)]] や [[closed]] の[[ストリーム]]で受信する可能性があります。)
[SRC[>>23]]
* 処理
[35] [[受信者]]は、 [[half-closed (remote)]] や [[closed]] で
[CODE[[[WINDOW_UPDATE]]]] [[フレーム]]を受信しても、
エラーとしては[['''なりません''']] [SRC[>>23]]。
[33] [[受信者]]は、[[フロー制御窓]]の増分が 0 なら、
[[ストリームエラー]] ([[接続]]全体に対するものなら[[接続エラー]])
[CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>23]]。
[37] [[payload]] の長さが 4 以外なら、[[接続エラー]] [CODE[[[FRAME_SIZE_ERROR]]]]
としなければ[['''なりません''']] [SRC[>>23]]。
* 設定
[19] [[設定]] [DFN[[CODE[[[SETTINGS_INITIAL_WINDOW_SIZE]]]]]] ([CODE[[[0x4]]]]) は、
[[送信者]]の[[ストリーム]]レベルの[[フロー制御]]の[RUBYB[[[初期窓サイズ]]]@en[initial window size]]を[[バイト]]単位で表します [SRC[>>18]]。
;; [21] [[設定]]は、すべての[[ストリーム]]で共通です。
[20] 初期値は、 2[SUP[16]]-1 です [SRC[>>18]]。
[22] 最大[[フロー制御窓]]サイズである 2[SUP[31]]-1 より大きな値は、
[[接続エラー]] [DFN[[CODE[[[FLOW_CONTROL_ERROR]]]]]] としなければ[['''なりません''']]
[SRC[>>18]]。