App Engine の負荷とインスタンス数

先日インスタンスとスレッドの関係を調べるために,いくつも同時にリクエストを発行してみたのだけど,4つしかインスタンスができなかった.エラーが起きるほどリクエストがたまっているにもかかわらず,インスタンスが増えてくれない.
どういう理屈でインスタンスが増えるのか,調べてみた.

結論

先に書いておくと,たぶんこんな感じ.

App Engine の挙動

App Engineでは,リクエストが到着すると,いったんそれをプールしておき,空いたインスタンスに投げるロードバランサーが入っている.このロードバランサーの中に10秒以上滞留すると,エラーになる.

実験

ほぼ等間隔でリクエストを出すプログラムを書いて実験した.Java で100スレッドのスレッドプールを作って実行した.はじめ cURLシェルスクリプトで書いていたら,プロセスが作れなくなって落ちたので...スレッドだと100スレッドぐらいなんでもないようだ.

(追記:100スレッドでは足りないことがわかったので,500スレッドで追試した.)

サーバ側では指定された秒数待つように設定した.

インスタンス数をn, サーバで待つ秒数を cとすると,1秒あたり捌けるリクエスト数は,n/c.これ以上リクエストがいくと,定常的にロードバランサー内のキューがあふれるようになる.

結果

req/s      c       n     あふれ
---------------------------
 1         1       1
 1         4       4
 1         8       4       * 
 2         1       3  
 2         2       4 
 2         4       4       *
 4         1       5 
 4         2       6       *
 4         4       5       *
 5         1       5
 5         2       9       *
 5         3       8       *
 8         1       8
 8         2      12       *
 8         3      10       *
10         1      11  
10         2      16       *
10         3      12       *
15         1      17
15         2      16       *
20         1      20
20         2      16       *
30         1      30       
30         2      18       *
50         0.5    30
50         0.75   30       *
50         1      30       *

所感

ロードバランサーで棄却されるジョブの数が影響していなさそうなのは,ちょっとびっくりした.実行時間が長いリクエストがインスタンスを占有している状態になっても,インスタンスが増えないわけだ.

処理を細分化して,複数のリクエストにしたほうが,インスタンスが増えやすくなって,エラーが起きにくくなる,ということか.

ちょっと気になる傾向として,同じリクエスト頻度で,処理時間が長くなると,逆に利用できたインスタンスの数が減っている.たとえば,20リクエスト/s の時,処理時間1秒で,リクエストと処理スループットがバランスする場合には20 インスタンス使えているが,
2秒になると16インスタンスしか使えていない.ロードバランサーで何か変なことが起きているのか?