情報科学屋さんを目指す人のメモ

方法・手順・解説を書き残すブログ。私と同じことを繰り返さずに済むように。

Nginxがキャッシュしてくれなかった原因と対策

Nginx (11) PHP (25) WordPress (76)

Yahoo!ニュースからのアクセスが集中したときに負荷を見ていたところ、「もしかしてキャッシュ聞いてない?」と確認してみたところ、リバースプロキシ(Nginx)が、ページをキャッシュしてくれておらず、毎回PHPが走っていることがわかりました。その原因を突き止め、応急処置をした時の話を書いておきます。時間がないので簡単なメモ程度で。

レスポンスヘッダ

Nginx越しにクライアントに届いているレスポンスヘッダに、次の表示がありました。

Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache

このレスポンスヘッダのお陰で、Nginxはキャッシュしてくれていませんでした。

また、最近有効にした自作のプラグインをオフにしてみると、これらのヘッダが出力されなかったため、原因はそのプラグイン内部の何処かである、ということになりました。

「no-cache」を探してみる

最初に「Pragma: no-cache」に目が行っていた自分は、次のコマンドで「no-cache」が含まれるファイルを探しました。

find (wp)/wp-content/ -name ‘*.php’ | xargs grep ‘no-cache’

しかし、「no-cache」の文字が見つかりはするものの、ヘッダへ出力するコードではなく、むしろレスポンスヘッダを読み取る側のコードでした。

「session_start」が原因

そこで見つけたのが、次のstackoverflowのページです。

参考:What could be adding "Pragma:no-cache" to my response Headers? (Apache, PHP) - Stack Overflow

ここに、類似した話が書いてあり、それほど人気ではないけれど私にとって心当たりのある、次のコメントが有りました。

I had a similar problem with Pragma: nocache

session_cache_limiter(false); prior to session_start(); seemed to suppress it. 引用元

試しに session_start(); をコメントアウトしてみると、no-cacheのヘッダは抑制されました。

直前に「session_cache_limiter('public');」を追加

どうやら、session_start();を実行すると、session_cache_limiterが行うキャッシュの設定がリセットされてしまうようで、session_start後も有効にするには、直前でsession_cache_limiterを実行しておく必要があるようでした(あんまり読んでない)。

参考:PHP: session_cache_limiter - Manual

stackoverflowでは「session_cache_limiter(false);」と紹介されていましたが、自分の場合はとりあえず直前に「session_cache_limiter('public');」を追加して、ちゃんとキャッシュが動作するようにしました。

コメント(0)

新しいコメントを投稿