HTTPリクエストの流れ — 「ください」の前に3往復
アドレスバーにURLを打ってEnterを押すと、一瞬でページが出ます。でもその裏では、名前を調べ、回線をつなぎ、鍵を交換し、やっと「ください」と頼むという手続きが順番に進んでいます。
図1で1段階ずつ進めて、誰と誰が何往復しているかを追ってください。スライダーでサーバーまでの距離を変えたり、2回目のアクセスに切り替えたりすると、どこに時間がかかっていて、どこが省けるのかが見えてきます。
頼む前に、3往復の準備がある
ブラウザがまずやるのは、URLの分解です。https から「暗号化して話す」、melon-shop.example から「相手の名前」、/items から「ほしいページ」を読み取ります。ところが名前のままでは相手に届かないので、DNSに住所(IPアドレス)を問い合わせます。これで1往復。
住所が分かったら、TCPで回線をつなぎ(1往復)、TLSで暗号の鍵を決めます(TLS 1.3 なら1往復)。ここまで来て、ようやく GET /items と「ください」を言えるのです。図1で段階を進めると、準備の矢印が本題より先にずらりと並ぶのが分かります。
遅さの正体は、距離 × 往復の回数
1往復にかかる時間を RTT(Round Trip Time)と言います。同じ国内なら数十ミリ秒、地球の裏側なら200ミリ秒を超えます。光の速さには上限があるので、回線を太くしてもRTTは縮みません。
図1のスライダーを右に振ると、サーバーの処理時間はそのままなのに、全体がみるみる伸びていきます。ページ表示の遅さの多くはサーバーの計算ではなく、往復の回数と距離で決まっているのです。CDNで近くにコピーを置くのは、このRTTを縮めるためです。
2回目が速いのは、準備を省けるから
図1で「2回目」に切り替えると、準備の3往復がまとめて消えます。DNSの答えはしばらく覚えておけるし(DNSキャッシュ)、一度つないだ回線は閉じずに使い回せる(Keep-Alive)からです。残るのは「ください」と「どうぞ」の1往復だけ。
HTMLが届いた後も話は続きます。ブラウザはHTMLを読みながらCSSや画像が必要だと気づき、同じ回線で追加のリクエストを出します。これも1往復ずつかかるので、読み込むファイルが多いページほど遅くなります。
- DNS
- ドメイン名からIPアドレスを調べる仕組み。答えはしばらくキャッシュされる。
- TCP ハンドシェイク
- 通信を始める前の接続のあいさつ。1往復ぶんの時間がかかる。
- TLS ハンドシェイク
- 暗号化の鍵を決める手続き。HTTPSで必要。TLS 1.3 では1往復。
- RTT
- 相手との1往復にかかる時間。距離でほぼ決まり、回線の太さでは縮まない。
- Keep-Alive
- 一度つないだ接続を閉じずに、次のリクエストでも使い回すこと。
まとめ
URLを打ってからページが出るまでに、DNS・TCP・TLSの準備で3往復、「ください」と「どうぞ」で1往復、さらに追加のファイルで何往復もかかります。遅さを決めるのは多くの場合往復の回数 × 距離。キャッシュ、接続の使い回し、近くに置くCDN――速くする工夫の多くは、この往復を減らすか縮めるかのどちらかです。