なぜ「無駄なパケット」を飛ばし続けるのか?ETagとIf-None-Matchで実現する通信の最適化
インフラエンジニアとして現場に立っていると、ふとパケットキャプチャを眺めたくなる瞬間がある。特に、レスポンスボディが数メガバイトある巨大なJSONを、ブラウザやクライアントが何度も何度も「同じもの」を律儀にダウンロードしている現場に出くわすと、思わず深いため息が出る。「そのデータ、さっきも送ったじゃないか」と。
帯域は有限だ。クラウドの転送量課金もバカにならない。Web APIのレスポンスを軽量化する手段として、圧縮やCDNの導入は一般的だが、実はプロトコルレベルでの「差分判定」こそが、最も手っ取り早く、かつ効果的な最適化手法である。
今回は、HTTPの条件付きリクエストにおける主役、`ETag`と`If-None-Match`について、現場の勘所を交えて解説する。
—
ETagとは何か:リソースの「指紋」
`ETag`(Entity Tag)は、サーバーがリソースに対して付与する一意の識別子だ。RFC 7232で定義されているが、難しく考える必要はない。これは「リソースの指紋」だ。
サーバーは、ファイルの内容をハッシュ関数(MD5やSHA-1など)にかけるか、あるいは最終更新時刻とサイズを組み合わせることで、そのバージョンを一意に特定する文字列を作成する。
HTTP/1.1 200 OK
Content-Type: application/json
ETag: “v1.0.4-a7f29b” <-- これがリソースの指紋
この`ETag`が重要なのは、クライアントが「さっきのデータ、まだ有効だよね?」とサーバーに尋ねるためのパスポートになるからだ。
---
304 Not Modified:何も送らないという贅沢
通信のシーケンスは極めてシンプルだが、この「何も送らない」という選択が、ネットワーク負荷を劇的に下げる。
1. 初回リクエスト: クライアントがリソースを取得し、サーバーから`ETag`を受け取る。
2. 2回目以降のリクエスト: クライアントはヘッダーに`If-None-Match`を付与する。
3. サーバー判定: サーバーは現在のリソースの`ETag`と比較する。
4. 判定一致: 変更がなければ、サーバーはボディを含めない`304 Not Modified`のみを返す。
通信フローのイメージ
sequenceDiagram
participant Client
participant Server
Client->>Server: GET /api/data (If-None-Match: “v1.0.4-a7f29b”)
Server->>Server: ETagを比較(一致!)
Server–>>Client: 304 Not Modified (ボディなし)
この「ボディなし」こそが、高トラフィックなAPIサーバーにおける救世主となる。
—
実装とデバッグ:現場で使えるコード例
理論だけでは実務はこなせない。実際にどのような挙動になるのか、curlやJavaScriptで確認する癖をつけておこう。
1. curlで検証する
手元のターミナルから、デバッグの第一歩を踏み出す。
初回取得(ETagを記録しておく)
curl -v -I https://api.example.com/data
2回目:If-None-MatchにETagを指定
304が返ってくれば、サーバー側の実装は正常
curl -v -H ‘If-None-Match: “v1.0.4-a7f29b”‘ https://api.example.com/data
2. ブラウザ(Fetch API)での挙動
モダンブラウザは優秀で、一度`ETag`をキャッシュすると、以降のリクエストで自動的に`If-None-Match`を付与してくれる。開発者ツール(Networkタブ)を開き、ステータスコードが`304`になっていることを確認してほしい。
// Fetch APIを使う場合、キャッシュポリシーを制御する
fetch(‘/api/data’, {
method: ‘GET’,
headers: {
// 既に保持しているETagをセット
‘If-None-Match’: ‘”v1.0.4-a7f29b”‘
}
}).then(response => {
if (response.status === 304) {
console.log(‘キャッシュが有効です。帯域を節約しました!’);
} else {
return response.json();
}
});
—
インフラ担当者が陥りやすい罠
最後に、現場でよくある失敗談を共有しておく。
- ハッシュ計算のコスト: 巨大なファイルに対して毎回SHA-256を走らせると、CPU負荷が無視できなくなる。`ETag`生成には、ファイルサイズや最終更新日時を組み合わせた軽量な計算式を使うのが定石だ。
- Strong ETag vs Weak ETag: `W/”…”`というプレフィックスがついた`Weak ETag`を見たことはないだろうか。これは「意味的に等価であればよい(厳密なバイト一致は保証しない)」というマークだ。負荷分散環境(ロードバランサー配下)では、各サーバーで正確に一致させるのが難しいため、あえてWeak ETagを使うケースもある。
- CDNとの競合: CloudFrontやFastlyを通している場合、これらの中間サーバーが`ETag`を書き換えることがある。オリジンサーバーの意図と一致しているか、レスポンスヘッダーを必ず確認してほしい。
まとめ
`ETag`と`If-None-Match`は、HTTP/1.1の時代から続く枯れた技術だが、クラウドネイティブな現在において、その重要性は増すばかりだ。無駄な通信を削ぎ落とすことは、単なるコスト削減ではない。それは、ネットワークの混雑を緩和し、システム全体のレスポンス速度を向上させるという、エンジニアとしての矜持そのものだ。
さあ、今すぐお使いのAPIサーバーのレスポンスヘッダーを確認してみてほしい。そこに`ETag`は存在しているだろうか? もし無ければ、それがあなたのシステムが「余計なパケット」を垂れ流しているサインかもしれない。
コメント