fbpx

メニュー

CloudFlareのPage rulesでプロキシキャッシュやってみる

高橋文樹 高橋文樹

この投稿は 10年半 前に公開されました。いまではもう無効になった内容を含んでいるかもしれないことをご了承ください。

先日農薬入りピザの件でバズったため、1日で3万PVぐらいあったのですが、サイトが落ちていたという報告をPHP界の良心安藤さんからいただきました。たしかに、はてぶでも「見れない→見れた」というブコメを散見しました。

安藤さんがくれたCloudFlareのエラー画面
安藤さんがくれたCloudFlareのエラー画面

このサイトは生意気にもCloudFlareの有料版を導入している富豪ブログなのですが、CloudFlareがエラー画面を返していたようです。なんでそんなことになったのかということについてですが、再現性がないのでほとんど推測なのですが、こんな感じかと。

  • CloudFlareは主に静的なファイル(JS、画像、CSS)だけの配信に使っていた。
  • よって、ブログ本体(WordPress)へのアクセスは素通りし、さくらVPS 2GのNginxが対応
  • 戦いはNginx+PHP fpm + WordPress VS 3万PV * 60kbの様相を呈する
  • Nginx陥落。CloudFlareにはAlways Onlineという機能があり、サイトが落ちた場合は自動的にキャッシュを返すはずだが、そうならなかった
  • 結果、CloudFlareにはエラー画面が表示される

しばらく立って、一度もサーバにログインすることなく復活。なぜ?

Nginxが落ちたときはよく504 BadGatewayを返すのですが、それがそのまま出たんでしょうか。CloudFlareのブログに寄せられたコメントによると、500とか503の場合だけキャッシュを返さないという報告が上がっているのですが。

A server reboot will not necessarily kick this in. The Always Online feature will work ONLY with a 502 or 504 error being returned when we try to connect. It will not work for these errors:

500 internal server error
empty reply from server
503 service temporarily unavailable (we did try 503s at one point…but it actually created more problems than it solved).
Dammon Billian 

まあ、理由はよくわかりませんが、Nginxがアップアップになって見られなくなったわけです。さくらのVPSは突然制限かけられて激重になるから要注意とかも関係あるかなーとは思いましたが、とにかく3万/1dayに堪えられなかったわけですね。

同じ構成のカイ士伝がさくらVPS512MBで耐えきったことを考えると、チューニングが間違っているのではと思えなくもないですが、そこら辺は今度@wokamotoさんに聞いてみるとして、本題のCloudFlareですよ。

Page rulesを設定してみる

さて、CloudFlareはデフォルト設定だとHTMLやPHPといったファイルへのアクセスはキャッシュしません。しかし、Page rulesという機能を使うと、この設定を個別に上書きすることができます。試しに このサイトでabout以下をキャッシュするようにしてみました。設定はこんな感じ。

CloudFlareのPage rules
CloudFlareのPage rules
Custom caching
Cache everything (=全部キャッシュ)するを選択しました。クエリストリングを無視(ex. 外部サイト経由で付加される_utm_sourceを無視するとか)したり、色々できます。
Edge cache expire TTL
CloudFlare上のキャッシュ有効期限ですね。これはRespect all existing headerを採用しました。つまり、「Nginxが返すヘッダーを尊重せよ」ということですね。

さて、Nginxのヘッダーを尊重させるとどういうことができるかというと、アプリケーション側から明示的にキャッシュ有無や有効期限を指定できるということです。

たとえばWordPressには nocache_headers という関数があって、これを実行するとキャッシュが使われません。管理画面やログイン画面、コメントフォームなどに埋め込まれています。

今回は検証の為に /about/ だけではnocache_headersを実行し、それ以外(/about/wp-plugins/とか)はCloudFlareのキャッシュが有効になることを確かめます。

add_action(’template_redirect’, function(){
     if( is_page(‘about') ){
          nocache_header();
     }
});

PHPのセッション設定ではまる

さて、無事設定できたわけですが、なぜかすべてのページでCache-Control: nocache が出力されていました。よくよく調べてみると、PHPってセッション使うとこのヘッダーを吐くみたいですね。なので、session.cache_limiterをpublicに変更。無事ヘッダーも正常なものに変わりました。CF-CacheっていうのがCloudFlareでのキャッシュステータスですね。

Gianismというソーシャルログイン用のプラグインでセッションを使っているので、それのせいでしょう。ここら辺、今後は考えないとですねー。

aboutはキャッシュなし
aboutはキャッシュなし
プラグインページはキャッシュあり
プラグインページはキャッシュあり

ベンチを取ってみる

Apache benchで比較してみました。/about/about/wp-pluginsも対してサイズは変わらない(60kbぐらい)ので、対照実験として良しとします。

# about/wp-plugins(キャッシュあり)を検証
ab -n 1000 -c 100 https://takahashifumiki.com/about/wp-plugins/
-> Requests per second:    116.63 [#/sec] (mean)
# about(キャッシュなし)を検証
ab -n 1000 -c 100 https://takahashifumiki.com/about/
-> Requests per second:    22.40 [#/sec] (mean)

結果、/about/wp-plusins(CFキャッシュあり)では秒間116.63リクエスト、/about(CFキャッシュなし)では秒間22.40リクエストとなりました。約5倍ですね。元々のスコアが悪すぎる気もしますが……

とにかく、このPage rulesを使えばさくらのレンタルサーバとかしょぼい共有サーバでもかなりの負荷をかけられることになります。

nocache_headersみたいな機能はWordPressに限らずどんなアプリケーションでも簡単に実装できるので、とりあえずサイト全体にPage rulesを適用してしまい、管理画面とかログインとか、リクエストがPOSTのときとか、そういうときだけキャッシュさせないようにすると楽チンですね。

というわけで、次回バズったときは耐えられるようがんばります。終わり。

[429] [429] Client error: `POST https://webservices.amazon.co.jp/paapi5/getitems` resulted in a `429 Too Many Requests` response: {"__type":"com.amazon.paapi5#TooManyRequestsException","Errors":[{"Code":"TooManyRequests","Message":"The request was de (truncated...)

すべての投稿を見る

高橋文樹ニュースレター

高橋文樹が最近の活動報告、サイトでパブリックにできない情報などをお伝えするメーリングリストです。 滅多に送りませんので、ぜひご登録お願いいたします。 お得なダウンロードコンテンツなども計画中です。