• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
【18-C-4】Google App Engine - 無限の彼方へ
 

【18-C-4】Google App Engine - 無限の彼方へ

on

  • 8,504 views

 

Statistics

Views

Total Views
8,504
Views on SlideShare
7,981
Embed Views
523

Actions

Likes
14
Downloads
175
Comments
0

10 Embeds 523

http://d.hatena.ne.jp 385
http://devsummary.miukoba.net 112
https://twitter.com 5
http://twitter.com 4
http://s.deeeki.com 4
https://bizsol.pa-rk.co.jp 4
http://paper.li 3
http://webcache.googleusercontent.com 2
http://www.redditmedia.com 2
http://bluerabbit.hatenablog.com 2
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    【18-C-4】Google App Engine - 無限の彼方へ 【18-C-4】Google App Engine - 無限の彼方へ Presentation Transcript

    • Takashi MatsuoGoogle, Inc.Feb 18, 2011
    • App Engine to infinity and beyondTakashi MatsuoGoogle, Inc.Feb 18, 2011
    • 自己紹介松尾貴史 @tmatsuo App Engine Developer Advocate Kays Daddy http://code.google.com/p/kay-framework/
    • > 10万 Developers / Month > 15万 Apps / Week > 10億 Page Views / Day
    • App Engine のこれまで 3 年 - 進化を続けるプラットフォーム Apr 2008 Python launch May 2008 Memcache API, Images API Jul 2008 Logs export Aug 2008 Batch write/delete Oct 2008 HTTPS support Dec 2008 Status dashboard, quota details Feb 2009 Billing, Remote API, Larger HTTP request/response size limits (10MB) Apr 2009 Java launch, Bulkloader (DB import), Cron jobs, SDC May 2009 Key-only queries, Quota API Jun 2009 Task queue API, Django 1.0 support Sep 2009 XMPP API, Remote API shell, Django 1.1 support Oct 2009 Incoming email Dec 2009 Blobstore API Feb 2010 Datastore cursors, Async URLfetch, App stats Mar 2010 Denial-of-Service filtering, eventual consistency support May 2010 OpenID, OAuth, App Engine for Business, new bulkloader Aug 2010 Namespaces, increased quotas, high perf image serving Oct 2010 Instances console, datastore admin & bulk entity deletes Dec 2010 Channel API, 10-minute tasks & cron jobs, AlwaysOn & Warmup Jan 2011 High Replication datastore, entity copy b/w apps, 10-minute URLfetch Feb 2011 Improved XMPP and Task Queue, Django 1.2 support
    • ロードマップ SSL access on non-appspot.com domains Full-text Search over Datastore Support for Python 2.7 Background servers capable of running for longer than 30s Support for running MapReduce jobs across App Engine datasets Bulk Datastore Import and Export tool Improved monitoring and alerting of application serving Logging system improvements to remove limits on size and storage Raise HTTP request and response size limits Integration with Google Storage for Developers Programmatic Blob creation in Blobstore Quota and presence improvements for Channel API
    • 日本での事例 たくさんのミクシィアプリ the Actress - 60万ユーザー Mixi Xmas 2010 - 200万ユーザー 朝日新聞 - メディア配信サービス ソニー - Chan-Toru 業務用アプリケーションも多数
    • App Engine for Business とは?App Engine プラットフォームに加え 99.9% SLA クラウド SQL 有償サポート ドメインコンソール Hosted SSL
    • 本ありますプログラミング Google App Enginehttp://www.oreilly.co.jp/books/9784873114750/オープンソース徹底活用 Slim3 on Google App Engine for JavaISBN-10: 4798026999
    • アジェンダApp Engine で開発する際の注意点 Datastore の設計 最小限の仕事をする Datastore Contention を避ける シャーディングカウンター Fork-join queue Memcache を効果的に使用する さらなる高みへ
    • Datastore の設計 非正規化 を嫌がらない - No join 必要な index のみ作成 最小限の Entity Group トランザクションが必要な箇所のみ 可能なら速い方を使う query より keys_only query が速い query より get が速い 複数の get より batch get が速い kind の分割が有効なケース 一部のプロパティだけ取得 少しの失敗を受け入れる リトライ、deadline の指定
    • Datastore の設計 非正規化 を嫌がらない - No join 必要な index のみ作成 最小限の Entity Group トランザクションが必要な箇所のみ 可能なら速い方を使う query より keys_only query が速い query より get が速い 複数の get より batch get が速い kind の分割が有効なケース 一部のプロパティだけ取得 少しの失敗を受け入れる リトライ、deadline の指定
    • Datastore の設計 - 非正規化Beforefrom google.appengine.ext import dbclass User(db.Model): name = db.StringProperty() groups = db.ListProperty(db.Key)class Group(db.Model): name = db.StringProperty()user = User.get(user_key)group_names = [group.name for group in db.get(user.groups)]
    • Datastore の設計 - 非正規化Afterfrom google.appengine.ext import dbclass User(db.Model): name = db.StringProperty() groups = db.ListProperty(db.Key) group_names = db.StringListProperty()class Group(db.Model): name = db.StringProperty()user = User.get(user_key)# group_names = user.group_names
    • Datastore の設計 非正規化 を嫌がらない - No join 必要な index のみ作成 最小限の Entity Group トランザクションが必要な箇所のみ 可能なら速い方を使う query より keys_only query が速い query より get が速い 複数の get より batch get が速い kind の分割が有効なケース 一部のプロパティだけ取得 少しの失敗を受け入れる リトライ、deadline の指定
    • Datastore の設計 - 必要な index のみ作成from google.appengine.ext import dbclass MyModel(db.Model): name = db.StringProperty() total = db.IntegerProperty(indexed=False) index が増えると書き込み速度は遅くなります
    • Datastore の設計 非正規化 を嫌がらない - No join 必要な index のみ作成 最小限の Entity Group トランザクションが必要な箇所のみ 可能なら速い方を使う query より keys_only query が速い query より get が速い 複数の get より batch get が速い kind の分割が有効なケース 一部のプロパティだけ取得 少しの失敗を受け入れる リトライ、deadline の指定
    • Datastore の設計 - Entity GroupEntity Group 作成の方法class MyModel(db.Model): # ...# 単純にエンティティを作成すると、それ自体新しい Entity Group になるmy_entity = MyModel()my_entity.put()# 親を指定すると、親と同じ Entity Group に属するmy_second_entity = MyModel(parent=my_entity)my_second_entity.put()# 同じ kind である必要はないmy_third_entity = MyOtherModel(parent=my_second_entity)my_third_entity.put()
    • Datastore の設計 - Entity GroupEntity Group 作成の方法class MyModel(db.Model): # ...# 単純にエンティティを作成すると、それ自体新しい Entity Group になるmy_entity = MyModel()my_entity.put()# 親を指定すると、親と同じ Entity Group に属するmy_second_entity = MyModel(parent=my_entity)my_second_entity.put()# 同じ kind である必要はないmy_third_entity = MyOtherModel(parent=my_second_entity)my_third_entity.put()
    • Datastore の設計 - Entity Group 親子関係全てに Entity Group を使用するべきではない 例えば BlogEntry と Comment には不適切 基本的にはトランザクションが必要な箇所に使う 検索用インデックスを自前で作る時などにも有効
    • Datastore の設計 - Entity Group の使用例検索用インデックス - Beforeclass Sentence(db.Model): body = db.TextProperty() indexes = db.StringListProperty()query = Sentence.all().filter( "indexes =", search_word)search_result = query.fetch(20)fetch 時に不必要な indexes のデシリアライズが発生
    • Datastore の設計 - Entity Group の使用例検索用インデックス - Afterclass Sentence(db.Model): body = db.TextProperty()class SearchIndex(db.Model): indexes = db.StringListProperty()query = SearchIndex.all(keys_only=True). filter("indexes =", search_word)search_result = db.get( [key.parent() for key in query.fetch(20)])保存時に Entity Group を形成
    • Datastore の設計 非正規化 を嫌がらない - No join 必要な index のみ作成 最小限の Entity Group トランザクションが必要な箇所のみ 可能なら速い方を使う query より keys_only query が速い query より get が速い 複数の get より batch get が速い kind の分割が有効なケース 一部のプロパティだけ取得 少しの失敗を受け入れる リトライ、deadline の指定
    • Datastore の設計 非正規化 を嫌がらない - No join 必要な index のみ作成 最小限の Entity Group トランザクションが必要な箇所のみ 可能なら速い方を使う query より keys_only query が速い query より get が速い 複数の get より batch get が速い kind の分割が有効なケース 一部のプロパティだけ取得 少しの失敗を受け入れる リトライ、deadline の指定
    • Datastore の設計 - Entity 分割例: ファイルシェアリングサービス ファイル自身 メタデータ ファイルの一覧ページで必要なのはメタデータだけ ファイル自身とメタデータを別エンティティに分割 一覧ページでの処理が高速で無駄がなくなる
    • Datastore の設計 非正規化 を嫌がらない - No join 必要な index のみ作成 最小限の Entity Group トランザクションが必要な箇所のみ 可能なら速い方を使う query より keys_only query が速い query より get が速い 複数の get より batch get が速い kind の分割が有効なケース 一部のプロパティだけ取得 少しの失敗を受け入れる リトライ、deadline の指定
    • Datastore の設計 - リトライ、deadlinefrom google.appengine.ext import dbfrom google.appengine.runtime.apiproxy_errors import DeadlineExceededErrorfrom google.appengine.runtime import DeadlineExceededError as Ddef somefunction(somevalue): handmaid_key = db.Key.from_path("MyModel", 1) new_id = db.allocate_ids(handmaid_key, 1) new_key = db.Key.from_path("MyModel", new_id) my_entity = MyModel(key=new_key, name=somevalue) try: while True: sleep_ms = 100 try: db.put(my_entity, config=db.create_config(deadline=5)) break except (DeadlineExceededError, db.Timeout): time.sleep(sleep_ms) sleep_ms *= 2 except D: # Ran out of retry. Return an error to users.自動リトライのレシピ
    • 最小限の仕事をする大事な用語 ユーザー向けリクエスト(User Facing Request) インターネット側から来るもの全て バックグラウンドリクエスト(Background Request) TaskQueue, Cron 等大事なポイントユーザー向けリクエストは 1000 ms 以内で返すこと
    • 最小限の仕事をする - より速い方を使用 query より keys_only query query より get datastore より memcache memcache より global 変数(static 変数)
    • 最小限の仕事をする - Task Queue を使用 時間のかかる処理は Task Queue に投げる。 Channel API を使えば結果を簡単にプッシュ
    • Datastore Contention をさけるEntity または Entity Group に対しての書き込み目安:  1 秒に 1 度程度対策: Entity Group はなるべく小さくする シャーディングカウンターなどのテクニックを使用する
    • シャーディングカウンター - シンプルな実装例from google.appengine.ext import dbimport random http://goo.gl/8dGOclass SimpleCounterShard(db.Model): """Shards for the counter""" count = db.IntegerProperty(required=True, default=0)NUM_SHARDS = 20def get_count(): """Retrieve the value for a given sharded counter.""" total = 0 for counter in SimpleCounterShard.all(): total += counter.count return totaldef increment(): """Increment the value for a given sharded counter.""" def txn(): index = random.randint(0, NUM_SHARDS - 1) shard_name = "shard" + str(index) counter = SimpleCounterShard.get_by_key_name(shard_name) if counter is None: counter = SimpleCounterShard(key_name=shard_name) counter.count += 1 counter.put() db.run_in_transaction(txn)
    • Fork-join queueBuilding high-throughput data pipelines with Google App Enginehttp://goo.gl/ntlHシンプルなカウンターの例http://paste.shehas.net/show/137/
    • memcache を効果的に使用する使用例 人気のあるページを html 丸ごとキャッシュ memcache.incr を使用したカウンター 高速だが 100% 正確とは保証できない 頻繁に使用される entity や query 結果をキャッシュ
    • memcache を効果的に使用する基本パターンresults = memcache.get(results)if results is None: results = some_complex_work() memcache.set(results, results)# use results古いキャッシュを破棄する
    • AppStats - パフォーマンス測定用ツールBeforeAfterhttp://goo.gl/eYdhD
    • さらなる高みへ Request 数の Fixed Quota はデフォルト 500 QPS 程度 それ以上必要な場合は、Quota Increase のフォームから 申請するか私宛に相談してください Tablet Server の Split を抑制 頻繁に(数百/秒) Entity の作成などを行う場合 自動採番の id では Split を引き起こしやすい uuid などを key_name として使用する key_name を使用する場合でも、頭文字が類似だと Split が起きやすい Hash 値を前置する
    • まとめ Datastore に適した設計 最小限の仕事をする Datastore Contention を避ける Memcache を効果的に使用する AppStats を使用してパフォーマンス測定する Fixed Quota を増やす Tablet Server の Split を抑制
    • 無限の彼方へ
    • Takashi MatsuoGoogle, Inc.e-mail: tmatsuo@google.comtwitter: @tmatsuo