前回の記事では、DNSの名前解決によって、ユーザーをCDN(エッジサーバー)にルーティングする方法を学びました。DNSの名前解決により、エッジサーバーのIPアドレスが分かった後は、ユーザーはエッジサーバーとHTTPによる通信を開始します。
この記事では、HTTPの基礎について解説します。CDNの仕組みを理解するためには、Webサイトとユーザーが情報を交換するために使っているHTTPを理解することが近道になります。
HTTP (HyperText Transfer Protocol) とは
HTTPは、Webサーバーとクライアント(Webブラウザ等)との間で情報をやり取りするためのプロトコルです。HTTPは、Webページや画像、その他のリソースをインターネット経由で転送するための基本的なルールや規約を定めています。
HTTPには次のような特徴があります。
- リクエスト-レスポンスモデル: HTTPは、クライアントがサーバーにリクエストを送り、サーバーがそのリクエストに応じてレスポンスを返すというリクエスト-レスポンスモデルで動作します。 クライアント-サーバーモデルと呼ばれることもあります。
- ステートレス性: HTTPはステートレスなプロトコルです。つまり、一度のリクエストとレスポンスの間でのみ通信が発生し、その後のリクエストでは以前の状態を保持しません。サーバーがクライアントの状態を継続的に追跡する必要がないため、サーバーがシンプルになり、スケールしやすいというメリットがあります。一方で、ログイン状態を保持してユーザーに応じて表示するコンテンツを変えるといった挙動も必要とされます。そのため、HTTPのステートレス性を補完する方法として、HTTP Cookieという仕組みがあります。 Cookieについては後ほど解説します。
Webサイトが表示されるまでのプロセス
まずは、Webサイトが表示されるまでのクライアント-サーバーの通信を見ていきます。
- HTMLページの取得
- サブリソースを取得
この流れに沿って説明をしていきます。
1. HTMLページの取得
前述した通り、HTTPはリクエスト-レスポンスモデルのプロトコルです。 クライアントが、リクエスト(Request)をサーバーに送信し、その返答としてサーバーはレスポンス(Response)をクライアントに送信します。
ここで重要なことは、HTTPではサーバー側からクライアントに向けてデータを送ることはなく(※)、必ずクライアントからのリクエストを契機としてレスポンスを返すことです。
(※) HTTP/2のサーバープッシュ機能では、サーバーがクライアントからのリクエストなしでリソースの送信ができますが、ここでは例外として扱います。
HTTP リクエスト
HTTP リクエストは次の3つの要素で構成されています。
- リクエストライン
- メソッド(Method): 実行するアクションを示すリクエストメソッド(例: GET, POST,OPTION)。
- リクエストターゲット: リソースのURLまたはパス(例: “/index.html”)。
- HTTPバージョン: 使用しているHTTPのバージョン(例: HTTP/1.1)。
- ヘッダー
- リクエストに関する追加情報を提供するキーと値のペア。一般的なヘッダーには、次のものがあります。
Host
(ドメイン名)User-Agent
(クライアントソフトウェアに関する情報)Accept
(クライアントが処理できるレスポンスのタイプ)Content-Type
(送信されるボディのメディアタイプ)などがあります。
- ボディ(オプション)
- リクエストの内容が入ります。 ペイロード(Payload)とも呼ばれます。メソッドがGETやOPTIONの時はボディは存在しませんが、POSTでフォームデータなどがサーバーに送信される場合等では含まれます。
最も一般的に使用される、GETリクエストの例を見ていきましょう。
GET / HTTP/1.1
Host: www.bloomblock.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0
Accept: text/html
Cookie: wordpress_sec...
1行目を見ることでHTTP/1.1を使用し、/
に対してGETメソッドでリクエストをしていることが分かります。/
の部分は、取得するリソースに応じて/index.htmlなどに
変化します。
2行目以降は全てヘッダーです。
Hostヘッダーの情報から www.bloomblock.net
に対してリクエストを送信しており、User-Agentヘッダー(UA)の情報から送信元の端末はMac OSのFIrefox 121.0を使っていることが推測できます。
また、Accpetヘッダーにて、クライアントはhtmlをレスポンスするようにサーバーに要求しています。
加えて、Cookieヘッダーを指定し、以前サーバーから受け取ったCookieを付与することでサーバー側に状態(ステート)を伝えています。Cookieについては後述します。
このリクエストはGETなので、ボディはありません。
リクエストラインとヘッダーを見るだけで多くの情報が得られることが分かったかと思います。サーバー側では受け取ったリクエストラインとヘッダーの情報から実施すべき処理を判断し、レスポンスを返します。
HTTP レスポンス
HTTP レスポンスも同様に3つの要素で構成されています。
- ステータスライン
- HTTPバージョン: 使用しているHTTPのバージョン(例: HTTP/1.1)。
- ステータスコード: リクエストの結果を示す数値コード(例: 200は成功、404は見つからない)。
- ステータステキスト: ステータスコードを簡単に説明するテキスト(例: OK、Not Found)。
- ヘッダー
- リクエストのヘッダーと同様に、レスポンスに関する追加情報を提供するキーと値のペア。一般的なヘッダーには
Content-Type
(ボディのメディアタイプ)、Content-Length
(レスポンスボディのサイズ)、Cache-Control
(キャッシュの指示)、Set-Cookie
(クライアントでのCookie設定)などがあります。
- リクエストのヘッダーと同様に、レスポンスに関する追加情報を提供するキーと値のペア。一般的なヘッダーには
- ボディ(オプション):
- レスポンスの内容(ペイロード)。これはHTMLコンテンツ、画像データ、JSONオブジェクトなど、リクエストとサーバーに応じて異なります。
リクエストと同様にレスポンスも見ていきましょう。
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 15824
Cache-Control: max-age=3600
Set-Cookie: UserID=1; Max-Age=3600; Version=1
<html>
<title>Example Page</title>
</html>
1行目が、200 OKとなっているので、このリソースは問題なく取得できたことが分かります。
ステータスコードは先頭の数値を見ることでコードの意味を知ることができます。特に、エラーである4XXと5XXはエラーの主因がクライアントとサーバーのどちらにあるのかを切り分けるのに役立ちますので、覚えておきましょう。
- 1xx (情報レスポンス): リクエストは受け取られ、プロセスが続行されています。
- 2xx (成功): リクエストは正常に受け取られました(例:200 OK)。
- 3xx (リダイレクト): 追加のアクションが必要で、リクエストを完了するために他の場所へのリダイレクトが必要です(例:301 Moved Permanently)。
- 4xx (クライアントエラー): リクエストにエラーがあるか、リクエストを完了できません(例:404 Not Found)。
- 5xx (サーバーエラー): 有効なリクエストにもかかわらず、サーバーがリクエストを処理できないことを示します(例:500 Internal Server Error)。
ステータスコード一覧を見たい場合は、Mozillaのページが便利です。
2行目から5行目まではヘッダーです。
Content-Lengthが15824であるため、約15KBのボディを受け取ったことが分かります。
Cache-Controlは非常に大事なヘッダーです。名前の通り、このヘッダーはキャッシュする/しないや、キャッシュする時間を制御するのに使われます。WebブラウザとCDNのエッジサーバーは主にCache-Controlヘッダーを参照して、キャッシュの戦略を決めます。Cache-Controlヘッダーについては、次の回で重点的に扱います。
Set-Cookieは、こちらも名前の通りですが、Cookieをクライアントに送るために使われます。クライアントは、Set-Cookieの内容を保持し、次回りクエストの際にCookieヘッダーに同じ内容を付与します。これによって、クライアントとサーバーの双方で共通の状態(ステート)を持つことができるようになり、HTTPのステートレス性と相性の悪いログイン機能などを実現できます。
ここまで見てきた情報は、ブラウザに付属している開発者ツールのNetworkタブを使うと簡単に見ることができます。Google Chromeの開発者ツールは、次のショートカットで開くことができます。
- Windows/Linux:
Ctrl
+Shift
+I
- macOS:
Command
+Option
+I
2. サブリソースを取得
Webブラウザは、HTMLページを取得した後、解析を開始します。
HTML解析中に、CSS、JavaScript、画像などの外部リソースに遭遇すると、これらのリソースのダウンロードが開始されます。
例えば、CSSであれば、次のように<link>タグを使って、外部リソースとして読み込むことができます。 これがサブリソースを取得する動作です。
<link rel="stylesheet" type="text/css" href="styles.css">
現代のWebページはリッチ化していますので、数百のサブリソースを持つことも珍しくありません。そのため、サブリソースを効率良く取得することはユーザー体験にとって重要です。
サブリソースの取得のための通信は先ほど見たHTMLページの取得と同様です。クライアントから個別のサブリソースに対して、リクエストを発行し、サーバーからレスポンスを受け取ります。
HTTP Cookieとは
Cookieは、Webサイトがユーザーのブラウザに送信し、ユーザーのコンピューターに小さなデータファイルとして保存される情報のことです。Cookieは、Webサーバーによって生成され、Set-Cookieヘッダーを通じてブラウザに送信されます。ブラウザはこれを受け取り、後で同じサーバーにアクセスする際にCookieヘッダーを通して送り返します。
Cookieの主に次の用途で使われます。
- セッション管理: ユーザーのログイン情報、ショッピングカートの内容、ゲームのスコア、またはその他のサーバーが「記憶」すべき情報を保持します。
- 個人設定: ユーザーの言語設定、テーマ、その他の設定情報を保存します。
- トラッキング: ユーザーのブラウジング行動を追跡し、これを使用してパーソナライズされた広告やコンテンツを提供します。
HTTPのバージョン
HTTPはWebの進化とともに改善されてきています。
この記事を書いている時点では、HTTP/1.1、HTTP/2、HTTP/3の3つのバージョンが広く使われています。
HTTP/1.1が最も一般的な選択肢ではありますが、テクノロジーに敏感な企業を中心にHTTP/2が普及してきています。
HTTP/1.1では、多くのブラウザは1つのドメインに対して最大6つの並列接続までしか行いません。これは、1つのドメインから同時にダウンロードできるサブリソースの数を6つに制限してしまうため、サブリソースが多いWebサイトにおいては問題になりました。
HTTP/2は、1つの接続で複数のリクエストとレスポンスを同時に並行して処理できるため、特にサブリソースが多い場合にはパフォーマンスを向上させることができます。
HTTP/3については、Youtube等のGoogleサービスを中心に使われておりますが、2022年6月に国際標準になったばかりということもあり、普及はこれからという状態です。
HTTP/3では、これまでのTCPベースのHTTP/1.1やHTTP/2とは異なり、UDPベースのQUICプロトコルを使用しており、大幅な変更が加えられています。
現在は3つのバージョンが併存している状況ですが、これからユーザー体験を良くしていこうとしている場合は、HTTP/2が第一選択肢になります。HTTP/1.1に対してパフォーマンス向上が見込め、十分に普及しているので特にデメリットがないからです。
第3回で述べたように、サーバー側がHTTP/1.1にしか対応していなくても、CDNを導入することでユーザークライアントとはHTTP/2で通信をすることができます。
HTTP/3については、CDNで利用した場合に一部の機能が制限されるなど、まだデメリットも存在します。デメリットを理解した上で採用を検討するのが良いでしょう。
まとめ
本記事では、HTTPの基礎について学びました。HTTPの基礎を理解しておくとCDNを導入する時の設定値の理解が深まります。
次回は、HTTPのキャッシュ機能にフォーカスして解説します。CDNが提供するキャッシュ機能はHTTPのキャッシュ機能に基づいているため、CDNの設定値を考える上では、HTTPのキャッシュについて理解しておくことが重要になります。
CDN入門記事の一覧ページはこちらです。