スティルハウスの書庫の書庫

はてなダイアリーで書いてた「スティルハウスの書庫」を移転してきました。

#appengine の30同時リクエスト制限が撤廃

ひがさんのつぶやき

Nick said: The simultaneous dynamic request limit was eliminated in a recent SDK #appengine http://bit.ly/blUr32

同時リクエスト制限を撤廃だと!?(ガタッ

ご存じのとおりApp Engineではアプリケーションサーバー(App Server)が冗長化されており、アプリケーションにかかる負荷に応じて自動的にスケールアウトするというのが大きな特徴です。しかしこれまでは、デフォルトで「同時に処理可能なリクエスト数の上限は30まで」という制限が掛けられていました。例えば、1リクエストに1秒かかるアプリならば、スループット上限は30リクエスト/秒となります。

これはApp Engineの性能上の限界ではなく、実運用や実開発で用いられている「本物」のアプリケーションのみに大規模なスケールアウトを許可するための安全策です。そのため、Googleに個別にリクエストすることで、この30制限は外してもらうことができました(私は依頼したことがありませんが)。

ただこの制限は、私のように「とりあえず実開発じゃないけど、App Engineのスケーラビリティの実力を確かめてみたい」という場合に問題となります。とりわけTask Queueで並列処理するようなケースでは、処理全体を数100のタスクに分割して処理するため、30制限(およびタスクレートの上限)によってスループットが抑えられてしまいます。App Engine本来の性能をお手軽に試せなかったわけです。

30制限がなくなった!

しかし、ひがさんが見つけたNickさんのML上での書き込みによると、最新版SDKではこの30制限が撤廃されたようです:

Hi Peter,

The simultaneous dynamic request limit was eliminated in a recent SDK. It
has been replaced with the flexible provisioning system detailed in the FAQ
entry you quote.

It's correct that as long as you keep your latencies low, you should never
run into any sort of request limit.

ふむふむ、"flexible provisioning system"についてはFAQに詳しく書いてあるらしい。。確かにFAQに以前書いてあった30制限の記述がなくなり、代わりに以下のような説明がありました:

How many active requests can my app serve at one time?

Google App Engine allocates resources to your application automatically as traffic increases to support many simultaneous requests. However, App Engine reserves automatic scaling capacity for applications with low latency, where the application responds to requests in less than one second. Applications with very high latency (over one second per request for many requests) are limited by the system, and require a special exemption in order to have a large number of simultaneous dynamic requests. If your application has a strong need for a high throughput of long-running requests, you can request an exemption from the simultaneous dynamic request limit. The vast majority of applications do not require any exemption.

Applications that are heavily CPU-bound may also incur some additional latency in order to efficiently share resources with other applications on the same servers. Requests for static files are exempt from these latency limits.

訳してみた(強調は私):

アプリケーションが同時に処理できるアクティブなリクエストの数はいくつですか?

Google App Engineでは、トラフィックの増加に応じてアプリケーションにリソースを割り当てて、多数の同時リクエストを処理できる仕組みです。ただし、App Engineの自動的なスケールアウト機能は、個々のリクエストを1秒以下で処理する低遅延のアプリケーションにのみ提供されます。一方、遅延の大きなアプリケーション(多くのリクエストの処理に1秒以上かかるもの)は、システムによってスケールアウトが制限されるため、より多数の同時リクエスト処理を行うには特別な制限解除が必要です。具体的には、こうした遅いリクエストのスループットをどうしても高める必要のあるアプリケーションについて、同時リクエスト制限を外すようGoogleに依頼できます。もっとも、この制限解除を必要とするアプリケーションは多くありません。

またCPUリソースを多く消費するアプリケーションについても、同じサーバー上の他のアプリケーションとの間でリソースを効率的に共有するために、遅延が大きくなる場合があります。なお、静的ファイルに対するリクエストはこれらの制限の対象外となります。

Task Queueで試してみた

というわけで、さっそくDevFestでも使用したTask Queueによる並列処理デモを使って、スケールアウトの振る舞いが変わったか試して見ました。以前のバージョンからの変更点は以下の通りです。

  • タスクの粒度を小さくした:リクエストを1秒以下で処理するために、個々のタスクで検索するエンティティ数を1000件から500件に減らしました。これにより検索処理は500ms以下で処理されます。
  • App Serverインスタンス数の集約を変えた:以前はMemcacheエントリをロックしてインスタンス数を集約する実装でしたが、この方法ではタスクの粒度を小さくすると競合が多発して、結局リクエスト処理時間が1秒を超えてしまいがちとなりました。そこでロックレスキューインスタンス数を集約する実装に変更しました。
  • タスクレートを48/sにした:最新SDKではTask Queueのタスクレート上限が50/sまで引き上げられたので、それに合わせて変更しました。

これで全検索を何度か繰り返して「あっため」してみると、最大で20インスタンスまでスケールアウトすることが確認できました。

[1e052ebc]: 23
[81d431ab]: 6
[102fdc70]: 15
[4fd41a54]: 7
[09ce25df]: 13
[f2080831]: 8
[238ab876]: 14
[e236498d]: 21
[9a214644]: 6
[d081ebc0]: 1
[c61418c4]: 5
[41db0bc0]: 8
[4cb4bb5b]: 13
[33ea5e72]: 9
[df0bab7a]: 6
[f356a8d6]: 5
[0338f0a8]: 12
[7aed837e]: 4
[eb60733a]: 13
[01a6e741]: 11

Total 20 instances and 200 requests.

以前は何度トライしても10インスタンスしかスケールアウトしなかったので、およそ倍の規模となったかたちです。しかし正直なところ、

  • タスクレートの引き上げの影響も大きい? 今回の制限撤廃による効果なのか、いまいち分からない
  • MapReduce等に使うのなら、もう1ケタ〜2ケタくらい増えてほしいなぁ

という印象です。やっぱり実開発でがつんと使わないと分からないのかな〜。いずれにせよ、個人的にはやはりMapReduceサポートの準備かな?と思ったりしました。