今度はServletContext+UUIDで負荷分散状況を調べてみた #appengine
@higayasuoさんのつぶやき:
#appengine でリクエストを処理するスレッドは1インスタンスあたり1つという仮定は正しい。ただし、インスタンスの特定にRuntimeのhashCodeを使うのは間違いでFilterなどで起動時にServletContextにUUIDなどを突っ込んで調べるのが正しい
#appengine でJavaのRuntimeは多くのアプリケーションで共有されていて同じアプリケーションの複数インスタンスで共有されることもある
なるほど、、そこで今度は、Runtime.getRuntime().hashCode()の代わりに、ServletContextにUUIDを入れて識別する方法でTask Queueのコンテナインスタンス単位の負荷分散状況を調べてみました。こんなコードをサーブレットに書いて、ランダムIDを取得します。
final ServletContext sc = super.getServletContext(); String instId = (String) sc.getAttribute("instId"); if (instId == null) { instId = UUID.randomUUID().toString(); sc.setAttribute("instId", instId); }
これに対してTask Queueで69個のタスクを実行し、得られたログからidを集計した結果がこちら:
[091f09e0-5255-4208-a6d7-4df64bd70f2a] 6 [22920a1f-17ec-4d8b-be3f-4a5881518903] 6 [26171bd4-8f66-46cd-a754-758b93bd71b3] 6 [32a23443-8c65-411a-b984-714fbccc958e] 3 [3753cb1d-da36-4765-b320-97d585f804f8] 5 [3c29e854-f25c-4816-b0f6-1c23f4f366e7] 4 [586ed664-3696-48a7-9fdb-10661309c7c9] 5 [5925465f-33c7-4f43-92ee-c34bc15c44b5] 3 [81e017c5-ea84-46d3-9f8e-1db420cc26bd] 3 [83a78921-7d7c-4939-b8d9-a6fa6f8a844c] 4 [a5cc6e5e-94ea-4c04-b7ad-6c7941baedf1] 1 [ac1f62b7-053f-4f7e-8ba7-c0eca0f21f02] 5 [ad3981bc-c7cb-4eb9-bee6-a6c077bd68c5] 7 [af789ef5-aecc-408f-a265-07847c4d2919] 1 [c42db46a-427a-4ec5-b5a3-30e37cbd7888] 4 [dcb34116-7d10-4302-b1be-8a52aed21bed] 6 総合計 69
今回も前回と同様に、16個のコンテナインスタンスに対して負荷分散してる状況がわかります。すると1JVM=1コンテナインスタンスってことなのかなぁ。。
追記
ひがさんのコメントでご指摘いただいた点(識別の対象がコンテナではなくアプリケーションのインスタンスである点)を修正しました。ついでに、RuntimeのハッシュコードとServletContextのUUIDのペアでも集計してみました(r=がRuntime、i=がインスタンス)
[r=10292103:i=ca08a349-6bed-4ccc-9951-288e08b6bc1b] 4 [r=1119993:i=90228109-e8e6-496e-a1d2-884544b701b7] 6 [r=1122818:i=84ae4f57-135f-4ac2-ba3c-0745cd222190] 2 [r=13620718:i=56dce314-e413-4c4f-9164-33b8e17afd0e] 6 [r=14624872:i=5ef591f9-f411-4fa2-9e92-e0eb268dbd81] 7 [r=1496906:i=a60606ab-c065-4f3d-baa3-e18ba34532ad] 6 [r=17350388:i=1563cf15-59da-4150-8f05-0743fd337b3d] 6 [r=21924150:i=571a0e16-cd07-4031-8097-281ba9d5e584] 9 [r=30299896:i=2ad9a29c-d2b9-4bdc-9441-97ff92c0ea78] 6 [r=30652173:i=905cae70-56b7-4c99-8c4e-ec51d082c0ab] 4 [r=33245819:i=f2859bbb-fc04-4061-befb-13dc994e5082] 3 [r=3598249:i=985ae732-d0cc-457c-869a-26eabe096032] 5 [r=3872307:i=51f066a5-7b95-4682-a101-73e1ae0be752] 4 [r=5141948:i=60be17e8-61f0-4420-a9e9-b9edd1c800bf] 1 総合計 69
このデータを見る限りは、
- 1JVM = 1インスタンス
という対応付けになっているようです。一方、ひがさんが指摘されてたように、appengineのすべてのアプリでリクエストのThread IDは「11」に統一されてます。
#appengine どのアプリのThreadのidも11だしhashCodeも28409161っておかしくない? ThreadのidとhashCodeみんなも調べてみて
これは私の環境でも確認できました。どのアプリでもThreadのidは11で、hashCodeは28409161で固定されています。そのため、
#appengine でリクエストを処理するスレッドは1インスタンスあたり1つという仮定が正しいとする根拠は、Threadのidが同じVMでかぶることはないから
よって、
ということになります。てことは、たしか@WdWeaverさんが推測されてたように、個々のリクエストを個別のJVMに割り振ってるのかな〜〜という気がしてきました。