APIサーバーで503エラーが頻発したので、CloudFlareキャッシュで対応した話

SPA + APIサーバーのWebアプリを作っていたところ、APIサーバーが一斉アクセスを捌けなくて503エラーを頻発させていたので、CloudFlareキャッシュでさくっと対応した時の話です。

状況

SPA + APIのWebアプリでの話です。

SPAはVue.jsで作っていて、コンポーネントごとにAPIへjsonファイルをリクエストしているので、1ページ開くとAPIに対して50アクセス以上の同時アクセスが発生するので、ちょっと多めのユーザーが同時アクセスすると、すぐに503エラーを返してしまう状況でした。

APIコールが多いのは、静的情報を吐き出すところだったので、PHPプログラム側でキャッシュする設定をしたのですがあまり緩和されませんでした。

APIサーバーがさくらレンタルサーバーのライトプランだったので、何かの閾値に引っかかってる気もします。

解決方法

静的情報を吐き出すだけなので、CDNにキャッシュさせればいいじゃんということで、CloudFlareにキャッシュさせることで対処できました。

マルチドメインでキャッシュの有無を差別化

APIサーバー全体をキャッシュさせることはできないので、

  1. メインAPIサーバー(app.example.com)
  2. 静的方法APIサーバー(app2.example.com)

とドメインをわけて、(2)のほうだけCloudFlareでキャッシュさせました。

APIサーバーのプログラムは大元のフレームワークを読むように

APIサーバーは、PHPの自作フレームワークで構築されているのですが、index.phpがCore.phpを読み込んでプログラムを展開する形式だったので、app2.example.comのindex.phpの読み込み先Core.phpを、app.example.com側のものにすることで、1つのプログラムで2つのAPIサーバーを動かすようにしています。

あとは、SPA側で静的情報の時だけ(都道府県情報とか)app2を見るようにすれば、簡単にキャッシュさせた高速APIサーバーになってくれます。

CloudFlareの設定を「Cache Everything」にする

CloudFlareは静的ファイルをキャッシュしてくれますが、画像など指定されたファイルに限定されていて、指定された拡張子がないとキャッシュしてくれないようです。

そこで、CloudFlareのPage Ruleから、app2ドメインのみ「Cache Everything」という全部キャッシュする設定を適用することで、.jpgなどではないAPIサーバーの結果もキャッシュさせることができます。

「Cache Everything」の設定は、CloudFlareのメニューの「Page Rule」ページから設定できます。

「Create Page Rule」ボタンを押して、必須項目を入力してルールを作成します。考えてみたら、このキャッシュルールを使えば、ドメインを分けないでも出来ますね(汗)

If the URL matches

URLのマッチルール。今回はドメイン以下全部なので、「app2.example.com/*」と入力します。

Then the settings are

Add a Settingをクリックして、

  • Cache Level
  • Cache Everything

を選択します。

Orderは設定にもよりますが、Firstで問題ないと思います。

すべての入力が終わったら、Save and Deployを押します。

キャッシュ方式に変えてみてどうか?

実際に変えてみたところ、503エラーはなくなりました。動的に出すための本APIのほうの負荷も減ったので、一石二鳥という感じです。

ただし注意点もあって、CloudFlareにキャッシュされていないデータについては、CloudFlareがページを本APIに読みに行くので、アクセスが多いと503エラーにるという状況は同じです。このあたり、先にCloudFlareにキャッシュさせるためのバッチかなんかを作って対処する感じですね。


テクニカルなことはあまりありませんが、APIサーバーの負荷で困っている場合は、部分的にCloudFlareでキャッシュさせることで503エラーを軽減させる方法も、一つの案としてありだなと思いました。