ソースコードから理解する技術-UnderSourceCode

手を動かす(プログラムを組む)ことで技術を理解するブログ

gRPCの入門とAPIバージョニングについて

はじめに

gRPCでmicroserviceを作る以下のチュートリアルを写経してみました。
[Tutorial, Part 1] How to develop Go gRPC microservice with HTTP/REST endpoint, middleware…

この中でAPIのバージョニングを行うために、バージョンv1のフォルダを作っている処理がありました。
今回はバージョンを追加することができるかを確かめるため、v2フォルダを作成し、新しいバージョンのAPIを作成してみました。
以下、その時の手順になります。

前提条件

先のチュートリアルの一連の処理は実装してあるものとします。
またデータの格納先としてMySQLを使っているのですが、私はローカルのMySQLを使用しました。

バージョニングの手順

ではAPIの新たなバージョン「v2」を作成する手順です。

api/proto/v2/todo-service.proto に定義を追加。

api/proto/v2フォルダを作成し、v2のAPI用のtodo-service.protoファイルを作成します。
今回は全てのResponseの定義に「message」を追加しました。

https://github.com/SrcHndWng/go-learning-gRPC-microservice/compare/v1.0.0...v1.1.0#diff-6bf81ca75e48c17bfe1d6e7cf5b6de84

./third_party/protoc-gen.sh を実行して pkg/api/v2/todo-service.pb.go を作成

参照したチュートリアルではprotocコマンドの実行に、.shファイルを使用します。
./third_party/protoc-gen.shにv2のprotocコマンドを実行するよう追加します。

protoc --proto_path=api/proto/v2 --proto_path=third_party --go_out=plugins=grpc:pkg/api/v2 todo-service.proto

追加したら./third_party/protoc-gen.shを実行します。
実行するとv2用のpkg/api/v2/todo-service.pb.goが作成されます。

pkg/cmd/server.go、pkg/protocol/grpc/server.goにv2を追加。

サーバを起動するpkg/cmd/server.go、pkg/protocol/grpc/server.goに、v2のAPIをそれぞれ追加します。

https://github.com/SrcHndWng/go-learning-gRPC-microservice/compare/v1.0.0...v1.1.0#diff-a4874ae26fb75dd53cb22801a2441507

https://github.com/SrcHndWng/go-learning-gRPC-microservice/compare/v1.0.0...v1.1.0#diff-2b80d164c22689ccea25a0527d415c17

pkg/service/v2/todo-service.go に独自ロジックを追加

サーバ側の処理を記述するpkg/service/にv2フォルダを作成し、その中にtodo-service.goを作成します。
先にも書いたようにサーバ側の処理をこの中で実装します。
今回はv2独自のロジックとして、各APIのResponseにメッセージとして「v2API Message」を返却するようにしました。

https://github.com/SrcHndWng/go-learning-gRPC-microservice/compare/v1.0.0...v1.1.0#diff-bf95c4339b6a85e3c3d682e5e4bae737

cmd/client-grpc-v2/main.go にクライアント側の処理を追加

クライアント側からはv2のAPIを呼び出します。
今回は既存のv1とは別に新しいクライアントを作成しました。
cmd内にclient-grpc-v2フォルダを作成し、main.goを作成します。
処理自体はv1とほぼ同じで、v1の代わりにv2を呼び出しているだけです。

https://github.com/SrcHndWng/go-learning-gRPC-microservice/compare/v1.0.0...v1.1.0#diff-6780540a19e75fbafe09b11e580c5fdb

実行してみる

サーバをビルドし、起動します。
cmd/serverに移動してgo buildを行います。
起動は以下のようなコマンドとなります。

./server -grpc-port=9090 -db-host=localhost:3306 -db-user=YourUser -db-password=YourPassword -db-schema=YourSchema

v1、v2を呼び出すクライアントをそれぞれビルドします。
cmd/client-grpc、cmd/client-grpc-v2に移動してgo buildを行います。

まずはv1を実行してみます。

$ ./client-grpc -server=localhost:9090
2018/09/26 16:37:16 Create result: <api:"v1" id:2 >

2018/09/26 16:37:16 Read result: <api:"v1" toDo:<id:2 title:"title (2018-09-26T07:37:16.476193Z)" description:"description (2018-09-26T07:37:16.476193Z)" reminder:<seconds:1537947436 > > >

2018/09/26 16:37:16 Update result: <api:"v1" updated:1 >

2018/09/26 16:37:16 ReadAll result: <api:"v1" toDos:<id:2 title:"title (2018-09-26T07:37:16.476193Z)" description:"description (2018-09-26T07:37:16.476193Z) + updated" reminder:<seconds:1537947436 > > >

2018/09/26 16:37:16 Delete result: <api:"v1" deleted:1 >

続いてv2を実行してみます。

$ ./client-grpc-v2 -server=localhost:9090
2018/09/26 16:46:29 Create result: <api:"v2" id:1 message:"v2API Message" >

2018/09/26 16:46:29 Read result: <api:"v2" toDo:<id:1 title:"title (2018-09-26T07:46:29.05597Z)" description:"description (2018-09-26T07:46:29.05597Z)" reminder:<seconds:1537947989 > > message:"v2API Message" >

2018/09/26 16:46:29 Update result: <api:"v2" updated:1 message:"v2API Message" >

2018/09/26 16:46:29 ReadAll result: <api:"v2" toDos:<id:1 title:"title (2018-09-26T07:46:29.05597Z)" description:"description (2018-09-26T07:46:29.05597Z) + updated" reminder:<seconds:1537947989 > > message:"v2API Message" >

2018/09/26 16:46:29 Delete result: <api:"v2" deleted:1 message:"v2API Message" >

v2の方のResponseには、追加した「message:"v2API Message"」が表示されているのが分かるかと思います。

まとめ

このようにgRPCの複数のAPIのバージョンを共存させることができました。
バージョンを追加した際のソース差分は以下となります。

https://github.com/SrcHndWng/go-learning-gRPC-microservice/compare/v1.0.0...v1.1.0

また全部のソースは以下となります。
GitHub - SrcHndWng/go-learning-gRPC-microservice at v1.1.0