appengine ja night #13 開発事例紹介 mixi Xmas 2010 株式会社あゆた 毛利真克
自己紹介 <ul><li>毛利真克 </li></ul><ul><li>Twitter:@mouri45 </li></ul><ul><li>会社:株式会社あゆた </li></ul><ul><li>HP: http://www.ayuta.c...
mixi Xmas 2010 <ul><li>mixi 公式の mixi アプリ </li></ul><ul><li>ピーク時は 250 万ユーザが参加 </li></ul>
システム構成 makeRequest http request JSON WebPage GAE/J (FW:Slim3) クーポン在庫 及びタイアップ サーバ PC アプリ モバイルアプリ
Datastore 使用量 <ul><li>Datastore 使用サイズ: </li></ul><ul><ul><li>95GB </li></ul></ul><ul><li>Datastore 格納レコード数: </li></ul><ul>...
効果的な施策 <ul><li>設定情報を static 変数に保持 </li></ul><ul><li>mixi アプリの制約に対する施策 </li></ul><ul><li>spin-up に対する施策 </li></ul><ul><li>そ...
設定情報を static 変数に保持 <ul><li>設定情報を static 変数で保持し Memcache へのアクセスを減らす。 </li></ul><ul><ul><li>アプリケーション全体で利用するような設定情報は static 変...
設定情報を static 変数に保持 Datastore request request Memcache Static 変数 Static 変数 設定 ファイル アップロード Static 変数が空、または有効期限が切れている場合は Memc...
mixi アプリの制約に対する施策 <ul><li>10 秒制限 </li></ul><ul><ul><li>PC アプリで makeRequest で呼び出した WebAPI 及びモバイルアプリの画面は 10 秒以内にレスポンスが返らなければ...
Datastore アクセスの遅延現象 <ul><li>他のアプリで通常の状態だと 1req にかかる時間は数百 ms だが、たまに遅くなることがあると報告を受けていた。 </li></ul><ul><li>Datastore アクセスの遅延が...
JOIN停止対策1 <ul><li>request が queue にたまる時間を短くする。 </li></ul><ul><ul><li>GAE に request が送られた際に処理可能なインスタンスが存在しない場合、 request は q...
JOIN停止対策2 <ul><li>Datastore アクセス時の deadline の指定。 </li></ul><ul><ul><li>Datastore アクセスが遅延している状態では、アクセスに 10 秒以上要することがあり、その場合...
LowLevelAPI での指定方法 DatastoreServiceConfig config = DatastoreServiceConfig.Builder .withReadPolicy(new ReadPolicy(Consisten...
Slim3での指定方法 デフォルト値を指定する場合 <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?> <appengine-web-app xmlns=&quot;http:/...
Spin-upに対する施策 <ul><li>通常の運用をしている際は、それほど問題にならない。 </li></ul><ul><li>デプロイ時 (version を毎回変えていたので実際は version 変更時 ) に同時に Spin-up ...
その他施策 <ul><li>Warm Up Requestsの利用。 </li></ul><ul><li>queryよりbatch getを優先的に使用。 </li></ul><ul><li>不要なsingle property indexが作...
やらなかったこと <ul><li>本来であれば、使用するべきだが、数億エンティティ・数百 req/sec という環境下で検証が十分行えなかったためやらなかったこと。 </li></ul><ul><ul><li>カスタムインデックスとマージジョイ...
カスタムインデックスと マージジョイン <ul><li>下記の問題について、検証する時間がとれなかったこと、及びどちらも、 query 用にプロパティを用意することで single property index で代用できるため未使用とした。 ...
task queueの多用 <ul><li>ベル鳴らし時に、鳴らした相手へのポイント付与やアプリ内アクティビティの登録処理に利用したかったが、秒間数百回実行される可能性があったため、検証を行う必要があった。結果的に、時間が取れなかったため、 t...
失敗したこと <ul><li>GAEでPVの取得 </li></ul><ul><li>Keyの命名 </li></ul>
GAEでPVの取得 <ul><li>モバイルアプリの PV をサーバ側で取得する必要があったが、 GAE のログは、一定以上量がたまると消えてしまうため、別の仕組みが必要と判断。(ログのダウンロードツールも取りこぼしが発生すると判断) </li...
問題 <ul><li>予想以上に費用が高くついた… orz </li></ul><ul><li>最終的に EC2 に Apache を立ててログを集計する方法に変更 </li></ul>
keyの命名 <ul><li>entityのkeyの生成の際にnameを指定できるが、この文字列の先頭にタイムスタンプを利用している部分があった。(queryの結果が指定した条件以外の部分がkey順に取得されるのでその特性を利用しようとしていた...
問題 <ul><li>GAE の datastore は、 BigTable を利用している。 BigTable 上でデータは複数の tablet server により管理されている。 </li></ul><ul><li>ひとつの tablet...
解決策 <ul><li>key 文字列の先頭にハッシュ値をつけることでアクセスがひとつの tablet server に集中しないようにする。 </li></ul>12343 12344 12341 12342 ABC_12311 ABC_12...
<ul><li>GAEは、劇的なスピードで、機能追加・パフォーマンス改善が行われている。 </li></ul><ul><li>GAEはソーシャルアプリに向いている。 </li></ul><ul><ul><li>過去断念した人ももう一度トライして...
ご静聴ありがとうございました。
Upcoming SlideShare
Loading in …5
×

ajn13 MixiXmas2010

1,791 views

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,791
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
8
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

ajn13 MixiXmas2010

  1. 1. appengine ja night #13 開発事例紹介 mixi Xmas 2010 株式会社あゆた 毛利真克
  2. 2. 自己紹介 <ul><li>毛利真克 </li></ul><ul><li>Twitter:@mouri45 </li></ul><ul><li>会社:株式会社あゆた </li></ul><ul><li>HP: http://www.ayuta.co.jp </li></ul><ul><li>最近の仕事:ソーシャルアプリの受託開発 </li></ul><ul><li>「これから始める人のための iPhone アプリ開発勉強会」主催 ( http://bit.ly/cDT4x6 ) </li></ul>
  3. 3. mixi Xmas 2010 <ul><li>mixi 公式の mixi アプリ </li></ul><ul><li>ピーク時は 250 万ユーザが参加 </li></ul>
  4. 4. システム構成 makeRequest http request JSON WebPage GAE/J (FW:Slim3) クーポン在庫 及びタイアップ サーバ PC アプリ モバイルアプリ
  5. 5. Datastore 使用量 <ul><li>Datastore 使用サイズ: </li></ul><ul><ul><li>95GB </li></ul></ul><ul><li>Datastore 格納レコード数: </li></ul><ul><ul><li>201,244,067 件 </li></ul></ul>
  6. 6. 効果的な施策 <ul><li>設定情報を static 変数に保持 </li></ul><ul><li>mixi アプリの制約に対する施策 </li></ul><ul><li>spin-up に対する施策 </li></ul><ul><li>その他 </li></ul>
  7. 7. 設定情報を static 変数に保持 <ul><li>設定情報を static 変数で保持し Memcache へのアクセスを減らす。 </li></ul><ul><ul><li>アプリケーション全体で利用するような設定情報は static 変数に格納することで Memcache へのアクセスが減らせる。 </li></ul></ul><ul><ul><li>設定を反映させたい場合は全てのインスタンスの static 変数を更新する必要があるが、有効期限を設けて、定期的に更新するようにしておけば、デプロイしなおさなくても反映できる。 </li></ul></ul>
  8. 8. 設定情報を static 変数に保持 Datastore request request Memcache Static 変数 Static 変数 設定 ファイル アップロード Static 変数が空、または有効期限が切れている場合は Memcache or Datastore から取得
  9. 9. mixi アプリの制約に対する施策 <ul><li>10 秒制限 </li></ul><ul><ul><li>PC アプリで makeRequest で呼び出した WebAPI 及びモバイルアプリの画面は 10 秒以内にレスポンスが返らなければタイムアウトとして扱われる。 </li></ul></ul><ul><li>JOIN 停止 </li></ul><ul><ul><li>モバイルアプリでタイムアウトが一定時間に一定回数発生するとアプリに未登録のユーザが新規にアプリに参加することができなくなる。 </li></ul></ul>GAE 10s 10s
  10. 10. Datastore アクセスの遅延現象 <ul><li>他のアプリで通常の状態だと 1req にかかる時間は数百 ms だが、たまに遅くなることがあると報告を受けていた。 </li></ul><ul><li>Datastore アクセスの遅延が集中して起こることが原因。 </li></ul><ul><li>この状態に陥るとレスポンスタイムが 10 秒を超えるものも多く発生しているため mixi 側でタイムアウトとして扱われるようになり、 JOIN 停止になる懸念があった。 </li></ul>
  11. 11. JOIN停止対策1 <ul><li>request が queue にたまる時間を短くする。 </li></ul><ul><ul><li>GAE に request が送られた際に処理可能なインスタンスが存在しない場合、 request は queue に積まれ、処理可能なインスタンスができるまで待機する。この待機時間には制限時間があり、それを超えるとエラーとしてレスポンスされる。制限時間のデフォルト値は 10 秒であるため、制限時間に達してエラーになった場合は、 mixi 側でもタイムアウトとして扱われている。 </li></ul></ul><ul><ul><li>mixi の JOIN 停止の条件は、タイムアウトのみで、エラーなどは含まれない。 </li></ul></ul><ul><ul><li>根本的な対策ではないが、 queue にたまる制限時間を短くすることで GAE 上で 10 秒かかるまえにエラーとしてレスポンスを返し、 mixi 側でタイムアウトとして扱われないようにすることで、 JOIN 停止を回避するように対応した。 </li></ul></ul><ul><ul><li>※ 設定するには Google に依頼する必要がある </li></ul></ul>
  12. 12. JOIN停止対策2 <ul><li>Datastore アクセス時の deadline の指定。 </li></ul><ul><ul><li>Datastore アクセスが遅延している状態では、アクセスに 10 秒以上要することがあり、その場合は mixi 側でタイムアウトとして扱われる。 </li></ul></ul><ul><ul><li>Datastore アクセス時に DatastoreServiceConfig を使用することで Datastore アクセスの制限時間を指定することが出来る。 </li></ul></ul><ul><ul><li>こちらも根本的な解決策ではないが、エラーにしてしまうことで JOIN 停止を回避するように対応した。 </li></ul></ul>
  13. 13. LowLevelAPI での指定方法 DatastoreServiceConfig config = DatastoreServiceConfig.Builder .withReadPolicy(new ReadPolicy(Consistency.EVENTUAL)) .deadline(5.0); DatastoreService ds = DatastoreServiceFactory.getDatastoreService(config); ここは Javadoc からひっぱってきたけど EVENTUAL はデフォルトじゃないらしい ちなみに mixi Xmas2010 では Slim3 つかったので、この部分は利用していない
  14. 14. Slim3での指定方法 デフォルト値を指定する場合 <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?> <appengine-web-app xmlns=&quot;http://appengine.google.com/ns/1.0&quot;> <application>app-name</application> <version>1</version> <precompilation-enabled>true</precompilation-enabled> <system-properties> <property name=&quot;slim3.datastoreDeadline&quot; value=&quot;5.0&quot; /> <property name=&quot;java.util.logging.config.file&quot; value=&quot;WEB-INF/classes/logging.properties&quot; /> </system-properties> <sessions-enabled>false</sessions-enabled> <inbound-services> <service>warmup</service> </inbound-services> </appengine-web-app> アクセス毎に指定する場合 entity = Datastore. deadline (2.5).get(modelClass, key);
  15. 15. Spin-upに対する施策 <ul><li>通常の運用をしている際は、それほど問題にならない。 </li></ul><ul><li>デプロイ時 (version を毎回変えていたので実際は version 変更時 ) に同時に Spin-up が起こるため、 JOIN 停止になることがあった。 </li></ul><ul><li>これは、インスタンスの起動時間+ spin-up 時のアプリの処理が遅いために発生していると考えられる。 </li></ul><ul><li>Static 変数をフラグとして使用することで現在の request が spin-up かどうか判定可能なため、 spin-up であれば、レスポンスをすぐに返しクライアント側から request をリトライ(モバイルなら redirect で)することで、 mixi 側のタイムアウトが発生しづらくなるため JOIN 停止を回避することができる。 </li></ul><ul><li>※ この施策については検証時間が取れなかったため実施しませんでした。 </li></ul>
  16. 16. その他施策 <ul><li>Warm Up Requestsの利用。 </li></ul><ul><li>queryよりbatch getを優先的に使用。 </li></ul><ul><li>不要なsingle property indexが作られないようにする。 </li></ul>
  17. 17. やらなかったこと <ul><li>本来であれば、使用するべきだが、数億エンティティ・数百 req/sec という環境下で検証が十分行えなかったためやらなかったこと。 </li></ul><ul><ul><li>カスタムインデックスとマージジョイン </li></ul></ul><ul><ul><li>task queue の多用 </li></ul></ul>
  18. 18. カスタムインデックスと マージジョイン <ul><li>下記の問題について、検証する時間がとれなかったこと、及びどちらも、 query 用にプロパティを用意することで single property index で代用できるため未使用とした。 </li></ul><ul><ul><li>5 月ごろに別案件で、カスタムインデックスが作られないという事象が報告されたので念のため未使用。 </li></ul></ul><ul><ul><ul><li>( ただし、問題が報告されたのは、運用が始まって後からカスタムインデックスを設定したケースなので、最初から設定しておくケースについては特に問題ないかも ) </li></ul></ul></ul><ul><ul><li>同じく 5 月ごろ別案件で、件数が多い kind でマージジョイン利用時にカスタムインデックスの生成を促すエラーが報告されたので念のため未使用。 </li></ul></ul><ul><ul><ul><li>(こちらは、現在は問題ないかも。データさえたくさん登録すれば検証は簡単なので、お試しあれ) </li></ul></ul></ul>今もダメな事がある
  19. 19. task queueの多用 <ul><li>ベル鳴らし時に、鳴らした相手へのポイント付与やアプリ内アクティビティの登録処理に利用したかったが、秒間数百回実行される可能性があったため、検証を行う必要があった。結果的に、時間が取れなかったため、 task queue は決済機能など利用範囲を限定した。 </li></ul><ul><li>運用中、データリカバリのために利用した task queue が 1.4.0 から入った task queue のデータの quota 制限にかかっていたため、今回のアプリにおいては正しい判断であった。 </li></ul>Task queue のデータの quota は設定で変えられるとのこと
  20. 20. 失敗したこと <ul><li>GAEでPVの取得 </li></ul><ul><li>Keyの命名 </li></ul>
  21. 21. GAEでPVの取得 <ul><li>モバイルアプリの PV をサーバ側で取得する必要があったが、 GAE のログは、一定以上量がたまると消えてしまうため、別の仕組みが必要と判断。(ログのダウンロードツールも取りこぼしが発生すると判断) </li></ul><ul><li>別の GAE アプリに対して img タグを使ってリクエストを送りページ名を記録する方法をとった。 </li></ul>Html <img … http://.../pageName.gif 透過 gif Jsp でレスポンス生成時に http:// 別アプリ /{pageName}.gif にアクセスする img タグを出力 Mixi アプリが稼動しているものとは別の GAE アプリを用意。リクエスト毎にページ名を記録することで後で PV を集計できるようにする。 mixi アプリ用 GAE PV 用 GAE ログに関しては google のほうで対策を検討中らしい
  22. 22. 問題 <ul><li>予想以上に費用が高くついた… orz </li></ul><ul><li>最終的に EC2 に Apache を立ててログを集計する方法に変更 </li></ul>
  23. 23. keyの命名 <ul><li>entityのkeyの生成の際にnameを指定できるが、この文字列の先頭にタイムスタンプを利用している部分があった。(queryの結果が指定した条件以外の部分がkey順に取得されるのでその特性を利用しようとしていたため) </li></ul>key = Datastore. createKey (modelClass, keyName);
  24. 24. 問題 <ul><li>GAE の datastore は、 BigTable を利用している。 BigTable 上でデータは複数の tablet server により管理されている。 </li></ul><ul><li>ひとつの tablet server にアクセスが集中するか、サイズが 300MB を超えると tablet server の分割が起こり、その際に Datastore アクセスのタイムアウトエラーが発生しやすくなる。(ただし、問題になるのは数百 QPS ぐらいアクセスがあるような場合) </li></ul><ul><li>今回の問題は key 文字列の先頭にタイムスタンプを使用していたため tablet server にアクセスが集中してしまった。 </li></ul><ul><li>http://bit.ly/hW2QG7 </li></ul>http://bit.ly/gqOVZO Index となるプロパティにタイムスタンプのような連続した値が格納されるケースも注意が必要(ただし、高アクセスな場合のみ)
  25. 25. 解決策 <ul><li>key 文字列の先頭にハッシュ値をつけることでアクセスがひとつの tablet server に集中しないようにする。 </li></ul>12343 12344 12341 12342 ABC_12311 ABC_12312 12345 12346 12347 ABC_12345 GHI_12347 DEF_12346 DEF_12321 DEF_12322 GHI_12331 GHI_12332 アクセスが 集中する アクセスが分散される
  26. 26. <ul><li>GAEは、劇的なスピードで、機能追加・パフォーマンス改善が行われている。 </li></ul><ul><li>GAEはソーシャルアプリに向いている。 </li></ul><ul><ul><li>過去断念した人ももう一度トライしてみよう! </li></ul></ul><ul><li>GAE/J+Slim3+Eclipseの生産性がすばらしい! </li></ul>
  27. 27. ご静聴ありがとうございました。

×