こんにちは。ネットワークの深淵を愛してやまない、インフラアーキテクトです。
Web APIの設計において、「キャッシュ」は魔法の杖のような存在ですよね。正しく使えばサーバーの負荷を劇的に下げ、レスポンスを爆速にできます。しかし、一歩間違えると「ユーザーAにユーザーBのデータが見えてしまう」という悪夢のような事故を引き起こす諸刃の剣でもあります。
今回は、そんなキャッシュ事故を防ぎ、賢く出し分けるための要、「Varyヘッダー」について紐解いていきましょう。
—
郵便配達で例えるキャッシュの仕組み
まず、キャッシュの考え方を郵便配達でイメージしてみましょう。
あなたが巨大な図書館の司書だとします。誰かから「最新のニュースを教えて!」という手紙(リクエスト)が届いたら、あなたは本を広げて内容を書き写し、返信(レスポンス)を送りますよね。
ここで、手紙が来るたびに本を広げるのは大変なので、よく出る情報を「コピー」して机の端に置いておくとします。これがキャッシュです。
しかし、もし「英語で教えて」という手紙と、「日本語で教えて」という手紙が混ざっていたらどうでしょう? 日本語しかコピーしていない状態で英語の手紙を受け取ったら、誤って日本語の回答を渡してしまいますよね。
このとき、「手紙の言語の種類(条件)によって、置いておくコピーを分ける必要があるよ」と教えてあげるのが、今回紹介する Vary ヘッダーの役割なんです。
Vary ヘッダーがやっていること
Webサーバーはブラウザに対して、「このキャッシュは、リクエストに含まれるこのヘッダーの値が同じ時だけ使い回していいよ!」と宣言します。
例えば、ユーザーの認証情報(Authorization)や、ブラウザが対応している圧縮形式(Accept-Encoding)によって、返すべきデータが変わるケースは多いですよね。
もし Vary: Accept-Encoding と指定すれば、サーバーは「圧縮方式が違うなら、キャッシュを別々に作ってね」と中継地点(CDNやプロキシサーバー)に指示を出せるようになります。
設定の実践:どう書くのが正解?
では、実際に現場でよく使われる設定を見てみましょう。例えば、Nginxでレスポンスヘッダーに Vary を付与する場合、以下のような設定になります。
# Nginxの設定ファイルの一部
location /api/ {
# 圧縮形式と、ユーザーの認証状態によってキャッシュを分ける設定
add_header Vary "Accept-Encoding, Authorization";
# ...その他のキャッシュ設定
}
Python (Flask) で書くなら、こんな風に書けます。
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/api/data')
def get_data():
response = make_response("ここにAPIのレスポンスデータが入ります")
# このデータは圧縮形式によって出し分ける必要があることを伝える
response.headers['Vary'] = 'Accept-Encoding'
return response
注意!「なんでもかんでも」は禁物です
ここで一つ、インフラエンジニアとしてのアドバイスです。Vary ヘッダーは便利ですが、「指定しすぎない」ことが重要です。
例えば、Vary: User-Agent を指定したとしましょう。ブラウザの種類(Chrome, Safari, Firefox…)ごとにキャッシュを分けることになりますが、世の中には数え切れないほどのブラウザの種類があり、さらにバージョンまで細分化されます。
これをしてしまうと、キャッシュの効率がガタ落ちします。せっかく用意したキャッシュが、「微妙にブラウザの情報が違うから使えない!」と判断され、サーバーへの負荷が全く減らない……という本末転倒な事態になりかねません。
守るべき3つのポイント
1. 本当に必要なヘッダーだけを指定する: 基本は Accept-Encoding くらいで十分なことが多いです。
2. キャッシュキーの断片化を避ける: ユーザーごとに異なる値(例えば Cookie のセッションIDなど)を Vary に入れるのは厳禁です。キャッシュが一切効かなくなります。
3. CDNを活用する: 複雑な条件分岐が必要な場合は、Vary に頼るだけでなく、CDN(CloudFrontやCloudflareなど)のキャッシュキー設定機能を活用する方が、運用の柔軟性は高まります。
最後に:ネットワークを「意識」するということ
Vary ヘッダーの設定は、目に見えないパケットのやり取りを想像する力が必要です。「今、どこの誰が、どの条件でデータを受け取ろうとしているのか?」を頭の中でシミュレーションする。これこそが、優秀なインフラエンジニアへの第一歩です。
最初は難しく感じるかもしれませんが、まずは「このデータは誰にでも同じものを渡していいかな?」と自問自答することから始めてみてください。それができれば、あなたはもう立派なネットワークの守護者です。
また次回の記事で、ネットワークの深淵を一緒に覗いていきましょう!
コメント