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

1.034 visualizações

Publicada em

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

Publicada em: Tecnologia
0 comentários
1 gostou
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
1.034
No SlideShare
0
A partir de incorporações
0
Número de incorporações
261
Ações
Compartilhamentos
0
Downloads
6
Comentários
0
Gostaram
1
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

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

×