HTTP深掘りしてみた[HTTP/1.1とかHTTP/2って何が違うの？]

# はじめに

今後なんらかの場面で絶対に聞かれるであろう

- HTTP/3ってなんですか?
- HTTP/3とHTTP/2は何が違うんですか?
- HTTP/1.1と比較してHTTP/2って何がいいんですか？

といった質問に答えられるように、HTTPについて調べてみました。
特に参考にした文献は以下のとおりです。

- [Evolution of HTTP - MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP#http1.0_%E2%80%93_building_extensibility)
- [Introduction to HTTP/2 - web.dev](https://web.dev/articles/performance-http2)
- [High Performance Browser Networking - ILYA GRIGORIK](https://hpbn.co/)

以上は情報源として一定の信頼があるため、これらを参考にしました。

# 対象読者

- サービスの開発などに慣れてきて、HTTPの恩恵を預かってはいるものの、中身をほとんど理解していない人

自分のレベルとしては、Nextjsで書いたサービスをCloudflareを用いてローカルでドメイン公開できる程度です。サービス開発の知識はある程度溜まっているものの、その下で動いているHTTPの仕組みについてはほとんど理解していません。

# HTTP/3ってなんですか?

- `QUIC`というプロトコルを`TCP`の代わりにトランスポート層のプロトコルとして用いる
- `QUIC`はGoogleが開発したプロトコルで、`UDP`上で動作する
- 2022年10月時点で26%のサイトがHTTP/3をサポートしている
- HTTP/2は1つのTCPコネクションで動作するため、`TCP`によるパケットロス検知や順序制御が全てのストリームをブロックしてしまうという課題があった
- `QUIC`は複数のストリームを`UDP`上で走らせ、ストリームごとにパケットロス検知と順序制御を行うことで、全てのストリームをブロックすることなく通信を行うことができる

## QUICについて

- `TCP`はオプションとして`TLS`を用いるが、`QUIC`は最初のハンドシェイクの時点で`TLS`を組み込んでいる
- 最初から`TLS`を組み込んでいるため、`QUIC`は`TLS`を用いるかどうかについて通信を行う必要がなく、通信のセットアップに必要なメッセージ数が少なくなる
- 複数のストリームを`UDP`上で走らせ、ストリーム単位でパケットロス検知と順序制御を行うため、全てのストリームをブロックすることなく通信を行うことができる

# HTTP/3とHTTP/2は何が違うんですか?

- HTTP/3はトランスポート層のプロトコルとして`UDP`をベースとした`QUIC`というプロトコルと用い、HTTP/2は`TCP`を用いる
- HTTP/2は複数のストリームが1つのTCPコネクションで動作するため、1つのストリームで発生したパケットロス検知や順序制御によって全てのストリームがロックされる。一方で、`QUIC`はそれぞれのストリームにパケットロス検知と順序制御機能を提供するため、影響範囲はそのストリームに限定される
- `TCP`と異なり、`QUIC`は最初のハンドシェイクで`TLS`を要求するため、セットアップに必要なメッセージの数が少ない

# HTTP/1.1と比較してHTTP/2って何がいいんですか?

## HTTP/1.1の課題

- HTTP/1.1はリクエストを受けた順番でしかレスポンスを返すことができない
  - 下図に示すように、リクエスト1のレスポンスが遅い場合、リクエスト2,3のレスポンスも遅れる
  - 一応、並列化する方法もありそれはTCPコネクションを複数張ることだが、これは非常に遅い上に多くのブラウザは同時に複数のTCPコネクションを張ることを制限している(Chromeは6つまで)[参考:[Using Multiple TCP Connections](https://hpbn.co/http1x/#using-multiple-tcp-connections)]

```mermaid
sequenceDiagram
    participant Client
    participant Server
    Client->>Server: Request 1
    Client->>Server: Request 2
    Client->>Server: Request 3
    Server->>Client: Response 1
    Server->>Client: Response 2
    Server->>Client: Response 3
```

- 似たようなヘッダーを繰り返し送信するため、オーバーヘッドが大きい

## HTTP/2で提案された解決策

- HTTP/2は1つのTCPコネクションで複数のストリームを扱うことができる
  - それぞれのストリームは独立しており、Request1,2,3はそれぞれのレスポンスを待つ必要がない
  - 1度に張るTCPコネクションが1本で済むというメリットもある

```mermaid
sequenceDiagram
    participant Client
    participant Server
    alt stream 1
    Client->>Server: Request 1
    Server->>Client: Response 1
    end
    alt stream 2
    Client->>Server: Request 2
    Server->>Client: Response 2
    end
    alt stream 3
    Client->>Server: Request 3
    Server->>Client: Response 3
    end
```

- 似たようなヘッダーを圧縮し、オーバーヘッドを削減する
  - HTTP/2では、`HPACK`という圧縮形式を用いて以前のリクエストと重複するヘッダーを省略してリクエストを送信する[参考:[ヘッダー圧縮](https://web.dev/articles/performance-http2?hl=ja#header_compression)]

## HTTP/2特有の機能

- ストリームの優先順位付け
  - HTTP/2からストリームの多重化が可能になったため、効率的にリクエストとレスポンスを処理するため、それぞれの処理の優先順位をつけられるようになった
  - ストリームの依存関係も明示的に指定可能となったため、ストリームAがストリームBに依存する場合、ストリームBを先に処理するというようなことも可能になった

# おわりに

今回の調査を通じてインターネットを支える基盤技術の1つであるHTTPについて理解を深めることができ、通信インフラに関する解像度を高めることができました。
今回の調査の中で`TCP`や`UDP`といったプロトコルにも興味が出てきたため、また今度勉強してみようと思います。

# 参考

- [Evolution of HTTP - MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP#http1.0_%E2%80%93_building_extensibility)
- [HTTP - MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP)
- [QUIC - MDN Web Docs](https://developer.mozilla.org/en-US/docs/Glossary/QUIC)
- [REST API with HTTP/2 - Stack Overflow](https://stackoverflow.com/questions/31692868/rest-api-with-http-2)
- [HTTP/2対HTTP/1.1：Webパフォーマンスにどのように影響するのか？ - Cloudflare](https://www.cloudflare.com/ja-jp/learning/performance/http2-vs-http1.1/)
- [サービス間通信のための新技術「gRPC」入門 - さくらのナレッジ](https://knowledge.sakura.ad.jp/24059/)
- [Introduction to HTTP/2 - web.dev](https://web.dev/articles/performance-http2)
- [Using Multiple TCP Connections](https://hpbn.co/http1x/#using-multiple-tcp-connections)