巷で議論を呼んでいるGoogle App Engine(GAE)の料金改定ですが、拙作ウェブサービスtwistoireも当然対象となります。どのくらい課金されるようになるかというと、こんな感じ。
だいたい5$/day、つまり150$/month……高い!高いよ!
で、なぜこんなに課金されるかというと非常に簡単な話で、インスタンスを使い過ぎなんですね。課金単位がCPU時間からインスタンス時間に変わったのが大きいわけです。twistoireはcronでTaskQueueにtaskを積んでバッチ処理を回し続けるというつくりになっているので、5〜6インスタンス起動するということも珍しくありません。ということで、この利用インスタンス数を削れないか試すことになりました。
threadsafeをONにする
最初に行ったのは、1インスタンスで複数リクエストをさばくためにappengine-web.xmlにthreadsafeを書いたことです。実際これはとても有効で、起動インスタンス数が2〜3にまで減りました。
いや最初から使っとけよという話なんですが、従来はこれを有効にするメリットがそこまで無かったのです。Googleさんには多大な迷惑をかけていたのだと思いますが……コストをユーザーにフィードバックすることの大切さを改めて認識した次第です。
Max idle instancesとMin Pending Latencyを設定する
インスタンスが2〜3に減りましたが、20 tasks/minという処理量を考えるとまだまだ減らせそうです。管理コンソールのApplication Settingsを見てみるとMax idle instancesというそれっぽい設定項目があったので、解説を読んでみます。
Setting a low maximum means your application costs less to run, but may encounter more startup latency during spikes in request volume.
Adjusting Application Performance - Google App Engine — Google Developers
安くなるかもしれないけどレイテンシ悪化するぜ、みたいなことが書いてあります。このウェブサービスはcronが主体でブラウザからアクセスされることはあまり無いので、レイテンシが悪化しても問題ありません。最低の1に設定してみます。
さらにこの設定の下に、Min Pending Latencyという設定がありました。こちらもインスタンスの起動を抑える効果があるようです。これを最大にし、インスタンスの起動を抑制してみます。
これで平時はインスタンスが1個だけになりました。これなら無料クオータで乗り切れそうです……が、たまに3〜4このインスタンスが起動してしまいます。どうやら処理に時間がかかるユーザにぶちあたると、インスタンスが起動してしうようです。これでは無料クオータに入りきりません*1。
X-AppEngine-FailFast ヘッダを使う
ちぇーGAEが起動インスタンス数の上限を設定する機能を持ってれば済む話なんだけどなーちぇー、とか思って
idle instancesだけでなく、max instancesも設定できるといいな。1台で済むはずのアプリでも、たまに2台起動してしまうことがある。 #gaeja
と大人気なくつぶやいていたら@tmatsuo氏が気にかけてくださったようで、Backendsを使う方法について示唆していただきました。ありがとうございます。Backendsは高価で無料クオータが少ない(9時間)という先入観があったのですが、インスタンス数を制限するという使い道があるのですね。
今回はあわせて紹介してくださったX-AppEngine-FailFastヘッダを使ってみました。このヘッダはBackendsの設定として紹介されているのですが、どうやらフロントエンドインスタンスにも有効らしいです。
これを適用してもたまにインスタンス起動が認められますし、この機能によってtaskの発火が抑制されてもログに出たりしないので、残念ながら効き目はよくわかりません。この機能が機能しているのだとしたら、今起動しているインスタンスはcronによるものなのでしょう。taskだけでなくcronの発火を遅らせる機能があれば嬉しいですね。