猫野詩梨帳

かわいいはかしこい

gRPC with FlatBuffers

gRPC は Google が開発している RPC(リモートプロシージャコール)フレームワークなんですけど,デフォルトだと同じく Google 製の Protocol Buffer (Protobuf) というシリアライズフォーマットを用います.

Protobuf についてはこれをみてね↓

qiita.com

ただ gRPC 自体は JSON とか XML とか他のフォーマットにも拡張できるようにデザインされているということで,例えばこれもまた Google 製の FlatBuffers というシリアライズフォーマットがあるんですけど,これも使えます.

Flatbuffers はめちゃ速いらしいんですけれど使うのがちょっと難しいです.

あんまり例とかも見ないのでちょっと簡単な例を作ってみました.

github.com

データ定義はこんな感じで

namespace Quiz;

table QuizTable {
  question:string;
  answer:bool;
}

table QuizRequest {
  quizNumber:int;
}

rpc_service QuizService {
  FetchQuiz(QuizRequest): QuizTable;
}

サーバーに QuizRequest としてクイズ番号を送ると対応する QuizTable を返してくれる,みたいな感じになってます.超シンプル!

FlatBuffers の(デ)シリアライズを行っているのは util/builder/builder.go です.たとえば

func QuizTableBuilder(q *util.Quiz) *flatbuffers.Builder {
    builder := flatbuffers.NewBuilder(0)
    question := builder.CreateString(q.Question)
    answer := util.Bool2Byte(q.Answer)

    quizAPI.QuizTableStart(builder)
    quizAPI.QuizTableAddQuestion(builder, question)
    quizAPI.QuizTableAddAnswer(builder, answer)
    qtOfs := quizAPI.QuizTableEnd(builder)

    builder.Finish(qtOfs)
    return builder
}

まず builder を作って,そこにひたすらデータを詰めていきます.今回は QuizTable を詰めるだけですが.テーブルを詰めるときは XXXStart ~ XXXEnd の間で中身を詰めます.

そして実際に gRPC でクライアント / サーバ処理を行っているのが client/main.go, server/main.go です.このあたりはほぼ gRPC with Protobuf と同じですね.違いはオプションとして grpc.CustomCodec(flatbuffers.FlatbuffersCodec{}) を渡しているくらいです.

現状クライアントはただクイズデータをとってきて表示するだけですが,実際にクイズとして遊べるようにしてみたりすると面白いと思います.

感想

みんなクイズのゲーム (QMA) やろう!