dorapon2000’s diary

忘備録的な。セキュリティとかネットワークすきです。

HTTP/2のTCPレベルのHoLブロッキングとQUIC

HTTP/2はHTTP/1.1で問題だったHTTPレベルのHoLブロッキングを解消しました。しかし、TCPレベルのHoLブロッキングという問題が依然として残っています。。。。。。🤔🤔

ぐぐるとたくさん解説サイトが出てきますが、いろいろ調べて、自分の言葉に落とし込んでみます。

概要

  • HTTP/1.1にはHTTPレベルのHoLブロッキング問題がある
    • HTTP/2で解決する
  • HTTP/2にはTCPレベルのHoLブロッキング問題がある
    • HTTP/3で解決する
  • HTTP/3ではTCPを使わずに、HTTP/2におけるストリームを別々で管理する

HoLブロッキング とは

f:id:dorapon2000:20210411070906p:plain

HoL (Head of Line) ブロッキングとは、待ち行列ができている中で先頭の客しかサービスを受けられない場合、残りの人が待たされなくてはいけないことを指します。

コンビニで例えるなら、レジにお客さんが並んでいるとして、精算中の人以外の人はスマホをいじりながら待つ必要があります。そんな中、精算中の人がお金が足りないなどと言ってATMに駆け出したら、いらっとくるわけです。このような状況がHTTPでも同じように発生します。

HTTP/1.1

HTTPコネクションを張るということはTCPコネクションを張るということです。ここでの、コネクションという単語はどちらの意味でも取ることができます。

特徴

f:id:dorapon2000:20210411135230j:plain

  • KeepAliveすることにより1つのコネクションで複数のファイルを送信可能。
    • ただし単一コネクション内では並行には送れない(HoLブロッキング
  • コネクションは一般に1つのドメインに対して並列に6つまで張ることができる
    • HTTPの仕様ではなく、一般的なブラウザによる制約
  • 6つ以上張りたい場合はドメインを複数用意する(ドメインシャーディング)
    • 2つのドメインを用意すれば、最大12個のファイルを並列に送信できる

HTTPレベルのHoLブロッキング

1つのHTTPコネクションだけに注目します。

http://www.plantuml.com/plantuml/png/SoWkIImgAStDuKegoYylJYrIqBLJ059bG9QLWhjhY4AYeLv1NZeNI0miMw40Ksc58OSXXTjK8rmwOL8EgNafG7S10000

GET a1.pngGET a2.pngGET c3.png の順に、HTTPリクエストがクライアントの送信キューで順番待ちしているとします。a1.pngのレスポンスがどこかで損失した場合、サーバは再送しますが、その間GET a2.png以降のリクエストを送ることはできません。具体的には、a1.pngは複数のTCPパケットに分割して送られており、そのうちの1つ以上が損失するとこのような状況になります。

HoL=GET a 1.pngが、GET a2.png以降のHTTPリクエストをブロッキングしています。

HTTP/2

HTTP/1.1のコネクションが、HTTP/2ではストリームにあたります。そして、HTTP/2では単一のTCPコネクションで複数ストリームを扱うことで並行にファイルを送信します。

HTTP/2の説明は詳解HTTP/2をとても参考にしています。

特徴

f:id:dorapon2000:20210411170325p:plain

  • 単一のTCPコネクションを使う
    • 1つのTCPパケットに複数ストリームのバイナリが含まれる可能性もある
  • 100以上のストリームでファイルを並行に送信可能
    • 同時に流せる最大ストリーム数はブラウザやサーバによって異なるがapacheは100
    • ファイルごとにストリームが生成される(再利用不可)
    • HTTP/2が出た今、ドメインシャーディングは非推奨*1

TCPレベルのHoLブロッキング

f:id:dorapon2000:20210411170329p:plain

HTTP/2でストリームを謳っても、TCPの上で成り立つ以上、MTUのサイズに整えられたTCPパケットが送信されます。そのパケットが損失すれば、TCPの機能で再送と順序制御がされます。ここがネックなのです。

上図では、ストリーム1だけを含むパケットが損失したため再送されます。その再送パケット以外をブラウザが受け取ったとして、ストリーム2とストリーム3のデータはすべて揃ったのだから、緑とオレンジの画像は表示されると期待してしまいます。

しかし、実際はTCPはシーケンス番号通りの順にしか処理できないため、4つ目のパケットをキューに入れて、3つ目のパケットが来るまで待ちます。キューに入っている間はHTTP側はストリーム3のデータを取り出せないため、オレンジの画像も表示できないです。

HoL=順序が入れ替わったパケットが、後続のパケットの処理をブロッキングしています。

HTTP/2の欠点

ここから見えてくるのは、HTTP/1.1と比べてHTTP/2がパケットロスに弱いという性質です。HTTP/1.1では独立したTCPコネクションを張っていたため、パケット損失はそのコネクションにしか影響がありません。HTTP/2は後続のすべてのストリームに影響があります。

具体的には、2%のパケロスでHTTP/1.1のほうが性能がよくなるようです*2*3。ただ、2%のパケロス環境も相当なようで、現実ではそこまでネックにはならないみたいです。

HTTP/3のQUIC

TCPレベルのHoLブロッキング問題を改善しているのがHTTP/3です。HTTP/3はほぼHTTP/2+QUICの組み合わせを指すため、QUICが肝になります。

QUICの特徴

UDP上で構築されていますが、トランスポート層プロトコルに相当します。

  • TCPと同じような動作をする
    • コネクション志向
    • 再送制御
    • 輻輳制御
  • 複数のストリームを扱うことができ、各ストリームごとに制御することができる
    • アプリケーション層のHTTP/2のストリームの概念をトランスポート層まで落としてきたといえる
    • 特定のストリームのパケット損失は他のストリームに影響がでない

TCPだから問題だったHoLブロッキング問題を、TCPを使わないことで解決しています。大胆ですね汗。

まとめ

L4〜L7のことを調べていると、面白くて無限に文献を漁ってしまいます。QUICはすごいし名前も速そう!

参考文献