さてではgRPCの実装を始めていきます。
今日はインターフェイスの定義とprotocol bufferのコンパイルまで行いたいと思います。
protocol buffer
まずはじめにすることはprotocol bufferでAPIのインターフェイスを定義することです。
今回はありきたりではありますがTodoサービスインターフェイスを定義したいと思います。
proto/service.proto
というファイルを作成し、以下のように記述します。
syntax = "proto3";
package service;
service TodoAPI {
rpc GetTodo(GetTodoRequest) returns (GetTodoResponse) {}
rpc CreateTodo(CreateTodoRequest) returns (CreateTodoResponse) {}
rpc ListTodos(ListTodosRequest) returns (ListTodosResponse) {}
}
message GetTodoRequest {
string id = 1;
}
message GetTodoResponse {
Todo todo = 1;
}
message CreateTodoRequest {
Todo todo = 1;
}
message CreateTodoResponse {
bool success = 1;
string id = 2;
}
message ListTodosRequest {}
message ListTodosResponse {
repeated Todo todos = 1;
}
message Todo {
string title = 1;
string description = 2;
}
protoファイルの管理に関してですが、会社として明確に決められたものはありません。が、習慣として他のチームが使いうるものはproto専用のレポジトリに切り出して管理、チーム内部でのみ使われるインターフェイスの場合はそのサービスのレポジトリに置いてしまう場合が多いです。
また、配布の仕方としては生成されたファイルではなくprotoファイルのまま各自コンパイルしてもらう方法が推奨されています。理由としては利用側がどの言語を使用するかわからないこと、コンパイルのツールチェインがチームによって異なりうることがあります。
コンパイル
ではコンパイルしてみましょう。
コンパイラとして gogo/protobuf を使います。インストール等はレポジトリを参考にしてください。
生成するGoファイルはinternal/pb/service
パッケージ内に置くことにします。
$ protoc \
-I ./proto \
-I $GOPATH/src:$GOPATH/src/github.com/gogo/protobuf/protobuf \
--gogoslick_out=plugins=grpc:./internal/pb/service/ \
service.proto
無事service.pb.go
ファイルが生成されたでしょうか。
makeタスク
最後にこのコンパイルタスクをMakefileに残しておきましょう。
PROTO_DIR := ./proto
GENERATED_DIR := ./internal/pb
GENERATED_SERVICE_DIR := $(GENERATED_DIR)/service
.PHONY: protos
protos:
mkdir -pv $(GENERATED_DIR) $(GENERATED_SERVICE_DIR)
protoc \
-I $(PROTO_DIR) \
-I $(GOPATH)/src:$(GOPATH)/src/github.com/gogo/protobuf/protobuf \
--gogoslick_out=plugins=grpc:$(GENERATED_SERVICE_DIR) \
service.proto
これでAPIを変更してもmake protos
で簡単にコンパイルし直すことができます。
社内にはAPIドキュメントというものはほとんど存在しません。
詳細にコメントされたprotoファイルさえあればAPIの役割はほぼ理解することができます。
gRPCの強力さはこういうところに現れるな、と感じるところです。
明日は生成されたファイルを元にgRPCサーバープロセスを立ち上げたいと思います。