Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und relevantere Anzeigen zu schalten. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
Web APIでThriftを
シリアライザとして使う
2016/11/26
歌舞伎座.tech#12「メッセージフォーマット/RPC勉強会」
@h_kishi
⾃⼰紹介と今回のLTの内容
• スマホゲーム開発でテックリードをやっています。
• クライアントサイド: C#(Unity)
• サーバサイド: Scala(Play)
• 今年リリースしたゲームのWeb APIサーバの開発でメッセージ
フォー...
メッセージフォーマット
の選定について
メッセージフォーマットの選定
• 新規にゲームを開発するにあたって、2014年の終わり頃にメッセー
ジフォーマット(シリアライザ)の選定を⾏いました。
• APIレスポンスやマスターデータなどで利⽤
• JSONのつらみ
• 前タイトルまではJ...
シリアライザの選定基準
• シリアライズ・デシリアライズが(なるべく)⾼速に実⾏できる
• 通信量を減らすために、シリアライズされたデータがなるべく
⼩さなサイズになる
• 頻繁に更新するのでデータ構造に更新があっても後⽅互換を保
つことができ...
JSON/XML/MessagePack
• JSON/XML
• テキストフォーマットで、冗⻑でファイルサイズが⼤きい
• デシリアライズするのに⼀度⽂字列にしてからパースするため、⼀般
的に遅く、メモリも多く必要とする
• 型を持たないため...
Thtift vs Protocol Buffers v2
• Thrift: Facebook社製(現在はApache下のプロジェクト)
• Protocol Buffers: Google社製
• どちらも提供する機能は似ている
• IDL...
(余談)Protocol Buffers v3について
• 2016年の7⽉にv3.0.0がリリース
• C#もサポート
• Messageの定義でmapも利⽤可能に
• JSON出⼒もサポート
• AppleがSwift⽤のライブラリのapp...
Thriftの活⽤事例
protocol
レポジトリ
client
レポジトリ
server
レポジトリ
最新のC#の
コードを参照
最新のScalaの
コードを参照
クライアントエンジニア
必要なフィールドの
追加のリクエスト
サーバエンジニア
thriftファイル...
Web APIでThriftを使うExample
def index = Action {
val indexResponse = new IndexResponse
indexResponse.success = true
val proto...
ThriftのIDLを使う上で注意する点
• バイナリ上は、番号と型が紐づいている
• そのため、⼀度定義したフィールドの型を変更するとバイナリ
の互換性がなくなってしまう
• 型変更をする場合、新しいフィールドとして定義し直す⽅が良い
• 同...
Thriftを導⼊して良かった点1
• IDLファイルにコメントを書いておけば、それがWeb APIのド
キュメント代わりになった
• APIドキュメントがをちゃんとバージョン管理、メンテされる
• PRベースでフィールド追加のタスク依頼ができ...
Thriftを導⼊して良かった点2
• ⾃動⽣成されたコードは定型なので、IDLからコードを⽣成す
るタイミングで独⾃の処理をコードに差し込むことが容易
• 例えば:
• クライアントサイド: チート対策でプロパティにメモリの難読化処理
• サ...
終わりに
• 最初はIDLを書くのが⾯倒かもしれませんが、ある程度のチー
ム・プロダクトの規模になるとメリット出てくると思うので、
興味がありましたら導⼊を検討してみてください。
(余談)twitter/scrooge
• https://github.com/twitter/scrooge
• Twitter社製のScala⽤のThriftコードのジェネレータ
• 本家のバイナリと互換性があり、直接Scalaのコードが...
Nächste SlideShare
Wird geladen in …5
×

Web APIでThriftをシリアライザとして使う

1.240 Aufrufe

Veröffentlicht am

歌舞伎座.tech#12「メッセージフォーマット/RPC勉強会」のLT資料です。

Veröffentlicht in: Technologie
  • Als Erste(r) kommentieren

Web APIでThriftをシリアライザとして使う

  1. 1. Web APIでThriftを シリアライザとして使う 2016/11/26 歌舞伎座.tech#12「メッセージフォーマット/RPC勉強会」 @h_kishi
  2. 2. ⾃⼰紹介と今回のLTの内容 • スマホゲーム開発でテックリードをやっています。 • クライアントサイド: C#(Unity) • サーバサイド: Scala(Play) • 今年リリースしたゲームのWeb APIサーバの開発でメッセージ フォーマットとしてThriftを導⼊した件について話します。 • RPCフレームワークとしてのThriftの話ではないのでご注意。
  3. 3. メッセージフォーマット の選定について
  4. 4. メッセージフォーマットの選定 • 新規にゲームを開発するにあたって、2014年の終わり頃にメッセー ジフォーマット(シリアライザ)の選定を⾏いました。 • APIレスポンスやマスターデータなどで利⽤ • JSONのつらみ • 前タイトルまではJSONを利⽤ • パフォーマンスが出ない、メモリ消費が⼤きい (巨⼤なJSONを返すとゲームが⼀瞬⽌まってしまうことも) • ⻑期運⽤しているとレスポンスのフィールドが何を意味しているのかわから なくなって都度コードの調査が必要 • 上記に対応するのにドキュメント作ったり、バリデーションするのもなかな か労⼒が必要
  5. 5. シリアライザの選定基準 • シリアライズ・デシリアライズが(なるべく)⾼速に実⾏できる • 通信量を減らすために、シリアライズされたデータがなるべく ⼩さなサイズになる • 頻繁に更新するのでデータ構造に更新があっても後⽅互換を保 つことができる • ライブラリがC#とScala(Java)で提供されている • IDL (インターフェース定義⾔語)がある
  6. 6. JSON/XML/MessagePack • JSON/XML • テキストフォーマットで、冗⻑でファイルサイズが⼤きい • デシリアライズするのに⼀度⽂字列にしてからパースするため、⼀般 的に遅く、メモリも多く必要とする • 型を持たないため、型を保証するにはJSON Schemaなどでバリデー ションを⾏う必要がある • MessagePack • バイナリフォーマットのため、JSON/XMLよりは軽量・⾼速 • IDLは仕様策定はされてたけど今は凍結中?
  7. 7. Thtift vs Protocol Buffers v2 • Thrift: Facebook社製(現在はApache下のプロジェクト) • Protocol Buffers: Google社製 • どちらも提供する機能は似ている • IDLでデータ構造を定義し、コマンドを実⾏するとクラスファイルを⽣成 • int、bool、double、string、enum、listなどの型が使える • フィールドの追加による後⽅互換性は問題 • Thriftはそれ⾃体でRPCフレームワークとして動作、 Protocol Buffersは gRPCと組み合わせるとRPCで利⽤可能 • 以下の点からThriftを採⽤ • JavaとC#を本家がサポートしている (v2はC#がProtocol Buffersは3rd party製のライブラリのみだった) • IDLでMapやSetなどの⾼機能な型が使える点 • JSON出⼒もサポート
  8. 8. (余談)Protocol Buffers v3について • 2016年の7⽉にv3.0.0がリリース • C#もサポート • Messageの定義でmapも利⽤可能に • JSON出⼒もサポート • AppleがSwift⽤のライブラリのapple/swift-protobufを提供開 始 • 次回選定時はProtocol Buffersの⽅が有⼒かも?
  9. 9. Thriftの活⽤事例
  10. 10. protocol レポジトリ client レポジトリ server レポジトリ 最新のC#の コードを参照 最新のScalaの コードを参照 クライアントエンジニア 必要なフィールドの 追加のリクエスト サーバエンジニア thriftファイルの更新 C#/Javaのコード⽣成 ThriftのIDLの利⽤の流れ デシリアライズする コード追加 シリアライズする コード追加
  11. 11. Web APIでThriftを使うExample def index = Action { val indexResponse = new IndexResponse indexResponse.success = true val protocol = new TCompactProtocol.Factory() val serializer = new TSerializer(protocol) Ok(serializer.serialize(indexResponse)) } サーバでシリアライズ(Scala) var www = new WWW("http://localhost/index"); yield return www; var stream = new MemoryStream(www.bytes); var tProtocol = new TCompactProtocol(new TStreamTransport(stream, stream)); var indexResponse = new IndexResponse(); indexResponse.Read(tProtocol); クライアントでデシリアライズ(C#) struct IndexResponse { 1: bool success; } IDLでの定義
  12. 12. ThriftのIDLを使う上で注意する点 • バイナリ上は、番号と型が紐づいている • そのため、⼀度定義したフィールドの型を変更するとバイナリ の互換性がなくなってしまう • 型変更をする場合、新しいフィールドとして定義し直す⽅が良い • 同様の理由で、すでに消してしまっていても、⼀度使った番号 を再利⽤せずに新しい番号を使うようにする struct User ( 1: i32 id, 2: string name ) struct User ( 1: i64 id, // 互換性がなくなる! 2: string name ) idの型を変更 struct User ( 1: i32 _id, // 互換性のために残す 2: string name, 3: i64 id ) 新しくフィールドを追加 (古いidはそのうち消す)
  13. 13. Thriftを導⼊して良かった点1 • IDLファイルにコメントを書いておけば、それがWeb APIのド キュメント代わりになった • APIドキュメントがをちゃんとバージョン管理、メンテされる • PRベースでフィールド追加のタスク依頼ができる • IDLファイルを⾒なくても、IDEでクラス定義をすぐに確認でき る • マジックナンバーを使っていたところがenumで置き換えられ た
  14. 14. Thriftを導⼊して良かった点2 • ⾃動⽣成されたコードは定型なので、IDLからコードを⽣成す るタイミングで独⾃の処理をコードに差し込むことが容易 • 例えば: • クライアントサイド: チート対策でプロパティにメモリの難読化処理 • サーバサイド: validateメソッドの中⾝を書き換えて内容チェック
  15. 15. 終わりに • 最初はIDLを書くのが⾯倒かもしれませんが、ある程度のチー ム・プロダクトの規模になるとメリット出てくると思うので、 興味がありましたら導⼊を検討してみてください。
  16. 16. (余談)twitter/scrooge • https://github.com/twitter/scrooge • Twitter社製のScala⽤のThriftコードのジェネレータ • 本家のバイナリと互換性があり、直接Scalaのコードが作られ る • 試した時はScala/sbtのバージョンを落とさないと動かなかっ たので断念したけど、今は問題ないはず

×