二つの head of line(HOL) blocking
Web 周辺のコンテキストで (HOL blocking) と言うと、実際には二つの種類がある。
- HTTP での HOL Blocking
- TCP での HOL Blocking
この二つは違うものなので、話す場合は「どの」レイヤでの話なのかは明示したい。
HTTP の HOL Blocking
HTTP/1.1 のリクエスト-レスポンスの組は、常に順番を保ち同期的に行われる必要がある。
具体的に 1 つの TCP コネクション上で、 3 つの画像(a.png, b.png, c.png) を取得する場合、 HTTP リクエストは以下のようになる。
|---a.png---|
|---b.png---|
|---c.png---|
一つのリクエストが処理され、レスポンスを受け取り終わってから、次のリクエストを投げることになる。
必ず前のリクエストが終わってからでないと、次のリクエストは投げられない。
もし a.png のリクエストが詰まってしまうと、 b, c がいくらすぐ処理できても全体としては遅くなっていまう。
|-------------------------------a.png------------------|
|-b.png-|
|--c.png--|
先攻するリクエストが詰まることで、後続も Block される。
これは HTTP/1.1 での HOL である。
単純な回避策として、別のコネクションでやるというのが考えられる。ブラウザであれば、同時に 6 本程度のコネクションを貼っているが、リソースが 6 個以上あれば、結局個々のコネクションで同様のことが起こるのをさけることはできない。
HTTP/1.1 の pipelining という仕様は、(条件付きで)リクエストだけ先に投げてしまうことで、多少これを回避するが、レスポンスはかならず順番なので、 a.png がサーバ側で詰まっていた場合、思った程効果が得られない。
HTTP/2 の場合
HTTP/2 の場合は、リクエストはコネクション上に多重化される。
これは、 a~c.png が全て並行にリクエスト/レスポンスされる状態を意味する。
よって、 a.png が時間のかかる処理でも b, c.png は先に取得して表示できるということ。
|-------------------------------a.png------------------|
|-b.png-|
|--c.png--|
実質 HTTP/1.1 での HOL Block は HTTP/2 では起こらないと言える。
ちなみに、画像がたくさん合った場合、コネクションがパンクするのでは?という問題については、 HTTP2 はコネクション上での Flow Control や、重要なリソースを優先する Priority を仕様として備えているので、それらで細かく制御が可能。
TCP の HOL Blocking
TCP の HOL Blocking は、HTTP のリクエスト/レスポンスを TCP のパケットレベルに置き換えたものとイメージできる。
TCP はパケット送信時に、送達を保証するため、もしパケットがロスとすると再送する。
再送が発生する場合は、パケットの順序が逆転しないように後続のパケットは待たせる。
つまり、 TCP 上で 3 つのパケットを送る際、先攻のパケットがロストすると後ろが詰まる。
これは TCP での HOL Blocking となる。
例えば、 HTTP/2 で多重化されたリクエストは、 TCP 上では単なるパケットなので、パケットが詰まると全体が遅れるという問題は回避できない。
むしろ 1 本の TCP コネクションで全部多重化している分、複数の TCP を使っていたころと比べると影響範囲が大きい可能性すらある。(1 パケット詰まると、表示全体が詰まる)
|-----packet1------|xxx lost xxx|-----packet1-----|
|-packet2-|
|--packet3--|
MTCP(multipath tcp) を使うと、複数のコネクションを別経路で貼って、より遅延などが少ない方を選ぶといったこともできるようだが、普及についてはまだまだという認識。
しかし、これは別途モバイルでの接続など、移動端末では重要になってくるが、それはまた別の話。
QUIC の場合
QUIC は TCP ではなく UDP の上に、独自に TCP 相当の再送制御の仕組みを作り直しています。
そして、その多重化は、最初からパケットレベルの HOL Block が起こらないようにデザインされています。
|-----packet1------|xxx lost xxx|-----packet1-----|
|-packet2-|
|--packet3--|
よって HTTP/2 over QUIC になれば、両方の HOL Block の問題が解決することになります。
link
TCP 1 本にまとめたときの影響について調査された論文がある。
http://sarulab.inf.shizuoka.ac.jp/pdf/335_shikama.pdf