Upload
yuuki-furuyama
View
5.699
Download
1
Embed Size (px)
Citation preview
Copyright©DeNACo.,Ltd.AllRightsReserved.
スケーラブルGCPアーキテクチャ
February10,2017-DeNATechCon2017
[email protected].,Ltd.
Copyright©DeNACo.,Ltd.AllRightsReserved.
⾃⼰紹介
! 古⼭祐樹! オープンプラットフォーム事業本部システム開発部アライアンスシステムグループ
! DeNA! 2014/04新卒⼊社! 2014/09~Mobageの新プラットフォーム(NextBrowserPlatform)・ゲーム招待サービスの開発
! 2015/04~グローバルマーケット向けの⼤規模ゲーム⽤プラットフォーム開発
! @addsict! github.com/addsict
2
Copyright©DeNACo.,Ltd.AllRightsReserved.
このトークで話すこと
! GoogleAppEngineをベースにスケーラビリティの⾼いアーキテクチャを構成する時のポイントとなる点を説明します
! 特にAppEngineとCloudPub/Subの組み合わせ⼿法を重点的に話します
3
Copyright©DeNACo.,Ltd.AllRightsReserved.
GoogleAppEngine
4
Copyright©DeNACo.,Ltd.AllRightsReserved.
GoogleAppEngine(GAE)とは
! Googleが2008年(約10年前!)から提供しているWebアプリケーション実⾏プラットフォーム
! 特徴! アプリケーションより下側は⼀切気にしなくていい
! 広義のServerlessArchitecture! トラフィックに応じてインスタンス数が⾃動で柔軟にスケール! GCPの様々なサービスとの連携が容易
! アプリログはStackdriverLoggingに! BigQueryやCloudPub/Subなどとの認証もGAEのデフォルトの
アクセストークンを⽤いることで容易に呼び出せる
5
Copyright©DeNACo.,Ltd.AllRightsReserved.
GAEでスケールさせるためには何に気をつけるべきか?
1. Datastore! 特性を知りそれに⾒合った設計を⾏なう! 特にインデックス
2. ⾮同期タスク! 時間のかかる処理は⾮同期に実⾏する! 外部システムに引きづられないように
6
Copyright©DeNACo.,Ltd.AllRightsReserved.
GAEでスケールさせるためには何に気をつけるべきか?
1. Datastore! 特性を知りそれに⾒合った設計を⾏なう! 特にインデックス
2. ⾮同期タスク! 時間のかかる処理は⾮同期に実⾏する! 外部システムに引きづられないように
7
今⽇はこちらを紹介
Copyright©DeNACo.,Ltd.AllRightsReserved.
⾮同期タスク-リクエストの処理を分離してスケールさせる
! リクエストを! 同期的に処理する部分! ⾮同期的に処理する部分! に分離して実⾏する
! 得られる様々なメリット! より素早くレスポンスを返すことができる! 1つの処理を複数の処理単位に分離して独⽴して実⾏できる! 処理の特性に⾒合ったインスタンスを⽤意できる
! もちろんGAE以外の組み合わせも可能! 外部システムの調⼦に⼤きく引きづられないようになる
! 緩衝材としての⾮同期化
8
システム全体をスケールさせるためには⾮同期化が不可⽋
Copyright©DeNACo.,Ltd.AllRightsReserved.
TaskQueue-GAEの⾮同期タスク実⾏環境
! ⾮同期タスクを実⾏するためのジョブキューシステム! 特徴
! 2種類のQueue! PullQueue:Worker⾃⾝がジョブを取りに⾏く! PushQueue:Workerに対してジョブがプッシュされてくる
! PushQueue+GAEだと、⽤意したエンドポイントにHTTPリクエストが送られてくる! PushQueueへのジョブ登録はHTTPリクエストを送るかのように⾏なう
! メソッドを指定して〜(POST)! URLを指定して〜(/user/events)! ヘッダを指定して〜(X-My-Header:1,2,3)! ボディを指定して〜({“eventId”:“123”})
! DatastoreのトランザクションにTaskQueueのキューイングを含めることが可能
9
Copyright©DeNACo.,Ltd.AllRightsReserved.
TaskQueue-⾮同期HTTPクライアントとして使う
! HTTPでジョブが送られてくる! →⾮同期HTTPクライアントとして使える(+リトライ付き!)
! 使い所! AppEngineのサービス間通信をTaskQueueを介して⾏なう
! 「GAETaskQueueをマイクロサービスのサービス間通信として使う-addsict'sblog」
10
App Engine
Task Queue
App Engine
Enqueue PushPOST/eventsHTTP/1.1
Copyright©DeNACo.,Ltd.AllRightsReserved.
TaskQueue-スケーラビリティの問題
! AppEngineとの相性は抜群だが課題も・・・! TaskQueue(Push型)の実⾏レート
! 1つのキューあたり500tasks/secまでに制限される! それ以上の速度でタスクが登録されると処理が追いつかなくなる
! 解決策! シャーディング! 秒間1万タスクが想定される場合:20個のキューを⽤意
! my_queue_01,my_queue_02,...,my_queue_20! 管理が煩雑&マニュアル対応が⼊りスケールしない
11
Copyright©DeNACo.,Ltd.AllRightsReserved.
CloudPub/Sub
12
Copyright©DeNACo.,Ltd.AllRightsReserved.
CloudPub/Subとは
! GCPの提供する汎⽤Pub/Subミドルウェア! 特徴
! ⾼いスケーラビリティ! 秒間100万(!)メッセージの処理(https://cloud.google.com/pubsub/での公表値)
! Push型とPull型! TaskQueueと同じ概念
! GoogleAppEngineとの⾼い親和性! 特別なエンドポイント:POST/_ah/push-handlersで認証された
メッセージを受け取れる
13
Copyright©DeNACo.,Ltd.AllRightsReserved.
TaskQueueからCloudPub/Subへ
! 両者は⾮常に似ている! HTTPでタスク(=メッセージ)がPushされる! 200系のレスポンスを返すことでタスクが完了、削除される
! CloudPub/SubはTaskQueueの上位互換となり得るか?! PushされるHTTPリクエストを柔軟に設定できない...
! エンドポイントはSubscription毎に固定! アプリケーション独⾃のHTTPヘッダも付けられない
! Datastoreのトランザクションに含めることが出来ない...! Pub/Subへのリクエストだけ失敗したらどうする?
14
App Engine
App Engine
Publish PushCloud Pub/Sub POST/_ah/push-handlers
Copyright©DeNACo.,Ltd.AllRightsReserved.
CloudPub/Sub-柔軟にHTTPリクエストをPushさせる
! 柔軟にHTTPリクエストを設定するために1. attributesと呼ばれるkey/valueペアにHTTPリクエストの情報を埋め込む
2. リクエストのハンドリングを⾏なうコードの前にメッセージをほどき、HTTPリクエストを復元1. アプリケーションから⾒て通常のHTTPリクエストと透過的にする
3. Pub/Subが判別可能なレスポンスコードへの変換1. “202Accepted”→“200OK”への変換など
15
{ “attributes”: { “method”: “PUT”, “path”: “/events/100”, “headers”: “{\”X-My-Header\”: \”1,2,3\”}” }, “data”: “eyJmb28iOiAiYmFyIn0=” }
PUT /events/100 HTTP/1.1 Content-Type: application/json X-My-Header: 1,2,3
{“foo”: “bar”}
encode
decode
HTTPPubsubMessage
Copyright©DeNACo.,Ltd.AllRightsReserved.
CloudPub/Sub-確実にPublishするために
! TaskQueueにはあったDatastoreとのトランザクションがない! 基本的にPub/Subへのリクエストはリトライを数回⾏なうことで⾼い確率で成功する! (実測値)150msのタイムアウトでは99.96%の確率で1回で成功! 失敗しても1度リトライを挟むだけで99.998%まで上がる
! それでも失敗した場合は! TaskQueueにフォールバックさせる! 流れ:GAE→(TaskQueue→GAE)→Pub/Sub→GAE
! トランザクションではないが実⽤には耐えうる
16
Copyright©DeNACo.,Ltd.AllRightsReserved.
CloudPub/Sub-インスタンス爆発を防ぐためのフロー制御
! 外部システムに引きづられインスタンス爆発を引き起こす危険性がある! GAEでは「ユーザのリクエスト」と「⾮同期タスクのリクエスト」を同じインスタンスで処理する設計を取ることがあるため
! 例.! ⾮同期に通信しているAの調⼦が悪くてリクエストが遅い! →ユーザからのリクエストを処理できるインスタンスが減る! →インスタンスを増やして対処する! →Aが回復しないのでインスタンスが際限なしに増えていく
! 解決策:Pub/Subのフロー制御をする! “window”という設定値をDatastoreに持ち、どの程度Pub/Subからのリクエストを受け付けるかを定義する! windowに収まるようにランダムに失敗レスポンスを返す
! Pub/Subのslowstartな再送ロジックをうまく活⽤する! ある程度「わざと失敗させる」ことでインスタンス数は安定してくる
17
Copyright©DeNACo.,Ltd.AllRightsReserved.
CloudPub/Sub-フロー制御の例
18
App Engine
Cloud Pub/Sub
1.Push
Datastore
外部 システム
2.現在のwindowサイズを確認
3.windowサイズ⼩さい→4xxレスポンスを返却
なんだか調⼦が悪い…
3.windowサイズ⼤きい→実際の処理を実⾏
Copyright©DeNACo.,Ltd.AllRightsReserved.
最後に
! AppEngineとCloudPub/Subを使った⾮同期タスク処理を組み合わせることで、スケーラビリティの⾼いアーキテクチャを実現する⼯夫を紹介しました! 他にもDatastoreやAppEngineの中でも紹介したいTipsはありますが、それらはまた次回に!
! GCPの各サービスは⽇々改善されているため、本トークで話した課題がすぐに解決されていることもありうることに注意です
19