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.132 Aufrufe

Veröffentlicht am

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

Veröffentlicht in: Technologie
0 Kommentare
2 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

Keine Downloads
Aufrufe
Aufrufe insgesamt
1.132
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
278
Aktionen
Geteilt
0
Downloads
6
Kommentare
0
Gefällt mir
2
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

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のバージョンを落とさないと動かなかっ たので断念したけど、今は問題ないはず

×