Kengo's blog

Technical articles about original projects, JVM, Static Analysis and JavaScript.

Google App Engineの新料金に自作ウェブサービスを最適化した話

巷で議論を呼んでいるGoogle App Engine(GAE)の料金改定ですが、拙作ウェブサービスtwistoireも当然対象となります。どのくらい課金されるようになるかというと、こんな感じ。
f:id:eller:20110913221442p:image
だいたい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に設定してみます。
f:id:eller:20110913221444p:image

さらにこの設定の下に、Min Pending Latencyという設定がありました。こちらもインスタンスの起動を抑える効果があるようです。これを最大にし、インスタンスの起動を抑制してみます。
f:id:eller:20110914222932p:image
これで平時はインスタンスが1個だけになりました。これなら無料クオータで乗り切れそうです……が、たまに3〜4このインスタンスが起動してしまいます。どうやら処理に時間がかかるユーザにぶちあたると、インスタンスが起動してしうようです。これでは無料クオータに入りきりません*1

X-AppEngine-FailFast ヘッダを使う

ちぇーGAEが起動インスタンス数の上限を設定する機能を持ってれば済む話なんだけどなーちぇー、とか思って

idle instancesだけでなく、max instancesも設定できるといいな。1台で済むはずのアプリでも、たまに2台起動してしまうことがある。 #gaejaless than a minute ago via Twitter for iPhone Favorite Retweet Reply

と大人気なくつぶやいていたら@tmatsuo氏が気にかけてくださったようで、Backendsを使う方法について示唆していただきました。ありがとうございます。Backendsは高価で無料クオータが少ない(9時間)という先入観があったのですが、インスタンス数を制限するという使い道があるのですね。

今回はあわせて紹介してくださったX-AppEngine-FailFastヘッダを使ってみました。このヘッダはBackendsの設定として紹介されているのですが、どうやらフロントエンドインスタンスにも有効らしいです。
これを適用してもたまにインスタンス起動が認められますし、この機能によってtaskの発火が抑制されてもログに出たりしないので、残念ながら効き目はよくわかりません。この機能が機能しているのだとしたら、今起動しているインスタンスはcronによるものなのでしょう。taskだけでなくcronの発火を遅らせる機能があれば嬉しいですね。

結果

以上の施策を行った結果、インスタンス数はほぼ1で安定するようになりました。
f:id:eller:20110913221441p:image
気になる価格は……
f:id:eller:20110913221443p:image
だいたい1/10に抑えられました。データストア書き込みも頑張れば減らせると思いますが、$15/monthというコストはGoogle社のサービスに対する対価として納得がいく価格です。

ということで、twistoireは価格改定後もGAEにお世話になろうと思います。今後ともよろしくお願いします!

*1:最近[http://blog.shehas.net/2011/09/10/app-engine:title=無料クオータが24時間→28時間に拡大されるというアナウンス]がありましたので、この程度のインスタンス起動は吸収できるレベルかもしれません