インターネットで使われているHTTP( Hyper Text Transfer Protocol )ですが、高速化されてきています。僕なりの視点となりますが「なるほど」と思ったポイントをまとめました。
■HTTP/1.0
初期の頃に使われていたのが「HTTP/1.0」です。クライアントからリクエストを出す際に接続して、サーバがファイル返却したら切断していました(図1)。
図1
図1の青線と緑線は別々のリクエストなので、そのたびに接続/切断が行われます。文字情報が中心の頃はこれでも良かったのかもしれないのですが、サイトの1画面に含まれる情報量が増えてくると(本文や画像ファイルなど複数のファイルで構成されてくると)、リクエストのたびに接続/切断を行うことのオーバーヘッドがかなりかかるようになります。
※接続の際は「3ウェイハンドシェイク」と呼ばれる3回のやりとり、切断の際は4回のやりとりがクライアントとサーバ間で行われます。
そこで、次に登場したのが「HTTP/1.1」です。
■HTTP/1.1
HTTP/1.1 で導入された高速化の仕組みは「Keep-Alive」と「パイプライン」だと思います。それぞれについて説明します。
まずは、Keep-Aliveです(図2)。
図2
Keep-Aliveは、「1つのTCPコネクション」で複数回のリクエストの送信を可能にしました。クライアント、サーバのどちらかが「Connection:Close」をHTTPヘッダーに指定しない限り、TCPコネクションは張られたままになります。図2の青線と緑線は別々のリクエストですが、TCPコネクションを張り続けた状態で複数回のリクエスト送信が可能になります。これによりHTTP/1.0でリクエストごとに行っていた接続/切断時のオーバーヘッドは解消されます。
※オーバーヘッドは解消されますが、不要なTCPコネクションが滞留したりメモリ使用量が増加したりというデメリットもあります。そのため一定時間が経過したらTCPコネクションを切断する「タイムアウト」を設定するケースが多いです。
Keep-Aliveによりオーバーヘッドは解消されますが複数ファイルを取得する場合、前のリクエストのレスポンスが返るまで次のリクエストは「待ち」が発生します(図2の緑線のリクエストは青線のレスポンスが返るまで送信できない)。
これを効率化するために、パイプライン処理が行われるようになりました(図3)。
図3
パイプライン処理では青線のリクエストを送信したあとに緑線のリクエストも送信可能にしています。ただしこれには条件があって、クライアントは続けてリクエストを送れますがレスポンスも送った順に受け取る(リクエストとレスポンスの順序が同期している)必要があります。図3では青線のリクエストを先に送っているので、青線のレスポンスを先に受け取る必要があります。
FTTHなどブロードバンドが普及したことによりHTTP/1.1ではクライアントとサーバ間で「複数個のTCPのコネクション」を張った上でKeep-Alive、パイプラインを使用しての高速化もしています。
※TCPコネクションを複数個張るデメリットもあります。モバイルなどの低速回線ではTCPの接続/切断に時間がかかったり、帯域不足で遅くなったりしてしまうこともあります。
モバイルの普及も踏まえ、GoogleはHTTP/1.1を使用するのはなくSPDY(スピーディーと読む)というプロトコルを開発し提唱しました。これがHTTP/2のベースとなっています。
■HTTP/2
「HTTP/2」では1つのTCPコネクションを使いTLSで作成したトンネル内で非同期でリクエストを出すことを可能にしています(図4)。
図4
図4では青線、緑線、赤線の順でリクエストを送信していますが、レスポンスは送信した順である必要はありません。リクエストとレスポンスが非同期となる場合でもリクエストの送信が可能となりました(レスポンスを待つ必要がないのでリクエストはいつでも、いくつでも送信が可能です)。
またその他にも、HTTP/2では以下の技術を使って高速化を図っています。
[ HPACK ]
HTTPヘッダーの圧縮技術。HTTPヘッダーは同じ内容のものをやり取りしているケースが多く、前回送信分との差分(変更点)のみを送るようにしてヘッダー容量を削減します。
[ サーバープッシュ ]
クライアントが要求するファイルをサーバが予測し事前に送信する。例えばクライアントがHTMLファイルをリクエストしたときに、それに付随するCSSファイルも送信してリクエストの時間を短縮します。
2018/12/12追記
QUICでのHTTP通信の高速化 の記事を追加したので見てみてください。