Evansを使ったGolang × gRPC開発
IT技術
gRPCを用いたAPIサーバー開発
gRPCはgoogle社が開発したRPC通信のひとつで、マイクロサービス間での通信や速度が求められる場合によく使用されます。
gRPCではデータ転送のシリアライズフォーマットとしてProtocol Buffersを採用しており、protoファイルというIDLを記述しコンパイルすると、任意の言語のクライアント・サーバー用のコードを自動で生成してくれる優れものです。
またスキーマファーストの開発となるため、API仕様書が無くてもprotoファイルを見れば分かるといった開発ができることもメリットの1つとなります。
しかしREST APIであれば動作確認する場合にCurlやPostmanなどを使って簡単に動作確認ができますが、gRPCの場合はバイナリベースのため人間が目視して確認するには専用のクライアントツールを使う必要があります。
そこで本記事ではサンプルで作った簡単なgRPC APIサーバーに対して、EvansというgRPCクライアントツールを使って動作確認をする方法を説明していこうと思います。
Evansとは
改めてEvansとはgRPC向けサードパーティクライアントツールになります。
https://github.com/ktr0731/evans
他にもgRPC公式のgrpc_cliや特に有名なgRPCurlなどがあります。
その中でもEvansは他と比べて特徴的なのが、REPLモードとCLIモードの2つを提供していることが挙げられます。
REPLモード
最大の特徴であるREPLモードは他のクライアントツールにはない、インタラクティブなUIでサーバーとやりとりをすることが出来ます。
参考: 公式Github
使い方は後ほど説明しますが、実際に使ってみると非常に使いやすいです。
予測補完機能が優秀で次に何を入力すればいいか、選択肢は何があるかなどを画面上に従って入力するだけで使用することができます。
そのためAPI名なんだっけ...といったことはなく使い慣れていない場合でもサクサクと動作確認をすることができます。
CLIモード
CLIモードは他のgrpc_cliやgRPCurlと同じような、非インタラクティブなUIによる操作モードになります。
参考: 公式Github
使い方としてはコマンドラインからサービスやAPI名を入力してリクエストを送るとJSON形式でレスポンスを取得することができます。
ある程度慣れていればこちらの方が素速く使うことができますし、レスポンスがJSONで手に入るため他のコマンドラインを組み合わせることで様々な加工がしやすくCLIモードを使うことも非常に多いかと思います。
今回使うAPIサーバーのサンプル
ここからは簡単なgRPCのAPIサーバーを作って、実際にEvansを使って動作確認をしてみたいと思います。
従業員取得API
今回は従業員(Employee)のデータを返すAPIを作成しました。gRPCの開発は本記事の主旨ではないためどのようなAPIを作ったのかだけ簡単に説明いたします。
protoファイルは以下の通りです。
1syntax = "proto3";
2package proto.employee;
3
4option go_package = "gen/api";
5
6service EmployeeService {
7 rpc Employee (EmployeeRequest) returns (EmployeeResponse);
8 rpc Employees (EmployeesRequest) returns (EmployeesResponse);
9 rpc EmployeesByType (EmployeesByTypeRequest) returns (EmployeesByTypeResponse);
10}
11
12enum EmployeeType {
13 FullTime = 0;
14 PartTime = 1;
15}
16
17message Employee {
18 int64 id = 1;
19 string name = 2;
20 int32 age = 3;
21 EmployeeType type = 4;
22}
23
24message EmployeeRequest {
25 int64 id = 1;
26}
27
28message EmployeeResponse {
29 Employee employee = 1;
30}
31
32message EmployeesRequest {}
33
34message EmployeesResponse {
35 repeated Employee employees = 1;
36}
37
38message EmployeesByTypeRequest {
39 EmployeeType employeeType = 1;
40}
41
42message EmployeesByTypeResponse {
43 repeated Employee employees = 1;
44}
また従業員データはダミーデータとして以下のようにべた書きしています。
1func employeeList() []*api.Employee {
2 return []*api.Employee{
3 {
4 Id: 1,
5 Name: "Yamada",
6 Age: 20,
7 Type: api.EmployeeType_FullTime,
8 },
9 {
10 Id: 2,
11 Name: "Suzuki",
12 Age: 25,
13 Type: api.EmployeeType_PartTime,
14 },
15 {
16 Id: 3,
17 Name: "Sasaki",
18 Age: 45,
19 Type: api.EmployeeType_FullTime,
20 },
21 }
22}
Employee (従業員情報)
従業員情報にはID、名前、年齢、雇用形態の4つの情報を持ちます。
雇用形態はEnum型で正社員とパートの2パターンあります。
1message Employee {
2 int64 id = 1;
3 string name = 2;
4 int32 age = 3;
5 EmployeeType type = 4;
6}
7
8enum EmployeeType {
9 FullTime = 0;
10 PartTime = 1;
11}
ServiceとRPCメソッド
従業員情報に関して1件取得、全件取得、雇用形態別に取得の3種類となります。
1service EmployeeService {
2 rpc Employee (EmployeeRequest) returns (EmployeeResponse);
3 rpc Employees (EmployeesRequest) returns (EmployeesResponse);
4 rpc EmployeesByType (EmployeesByTypeRequest) returns (EmployeesByTypeResponse);
5}
Evansを使ってAPIコールする
では早速Evansを使って実際に動作確認をやってみようと思います。
Evansのインストール
まずはEvansをHomebrewを使ってインストールします。
1brew tap ktr0731/evans
2brew install evans
バージョン確認をして表示されればインストール完了となります。
1$ evans -v
2evans 0.10.9
また本記事ではEvansバージョン0.10.9を使っていきます。
コマンドとオプション
Evansに準備されている代表的なコマンドとオプションの一覧です。
コマンド | 説明 |
repl | REPLモードで実行する |
cli | CLIモードで実行する |
オプション | 説明 |
--proto | protoファイルのパスを指定する |
--host | gRPCサーバーのホストを指定 |
--port, -p | gRPCサーバーのポートを指定 (default "50051") |
--reflection, -r | gRPC reflectionを使用している場合 (default "false") |
gRPC リフレクションについて
基本的には--protoオプションを使って定義元となるProtocol Buffersファイルを指定する必要があるのですが、実際の開発現場では大量のファイルが作られることがほとんどです。
そうなってくると毎回個別に指定するのは非常に面倒になります。
そこでgRPCの公式が用意しているリフレクションの設定をサーバー側で登録していれば、毎回Protocol BuffersのIDLを直接的に読み込まずにメソッドを呼び出すことが出来るようになります。
https://pkg.go.dev/google.golang.org/grpc/reflection
今回もサーバー起動時にリフレクションの登録をしているためprotoの指定はせずに -r オプションを指定して実行していきます。
REPLモード
まずはREPLモードを使って動作確認してみます。
REPLモードとリフレクションオプションを指定して実行すると、このようにインタラクティブモードで立ち上がります。
1$ evans -r repl
2 ______
3 | ____|
4 | |__ __ __ __ _ _ __ ___
5 | __| \ \ / / / _. | | '_ \ / __|
6 | |____ \ V / | (_| | | | | | \__ \
7 |______| \_/ \__,_| |_| |_| |___/
8
9 more expressive universal gRPC client
10
11proto.employee.EmployeeService@127.0.0.1:50051>
RPCの実行をするためにはpackageとserviceを指定し、最後に実行するRPCメソッドを選びます。
1proto.employee.EmployeeService@127.0.0.1:50051> package proto.employee
2
3proto.employee@127.0.0.1:50051> service EmployeeService
4
5proto.employee.EmployeeService@127.0.0.1:50051> call Employee
途中はこのように入力の補完候補が出てくるため覚えたりコピペしてくる必要さえありません。
最後にrequestの引数である従業員IDを入力して実行すると
1proto.employee.EmployeeService@127.0.0.1:50051> call Employee
2id (TYPE_INT64) => 1
3{
4 "employee": {
5 "age": 20,
6 "id": "1",
7 "name": "Yamada"
8 }
9}
このように従業員情報を取得することができました。
もし引数がEnum型の場合は選択肢が出てきます。
1proto.employee.EmployeeService@127.0.0.1:50051> call EmployeesByType
2Use the arrow keys to navigate: ↓ ↑ → ←
3? employeeType (TYPE_ENUM) =>
4 ▸ FullTime
5 PartTime
他にもshowコマンドやdescコマンドで一覧や詳細情報を表示することも可能です。
1proto.employee.EmployeeService@127.0.0.1:50051> show message
2+-------------------------+
3| MESSAGE |
4+-------------------------+
5| EmployeeRequest |
6| EmployeeResponse |
7| EmployeesByTypeRequest |
8| EmployeesByTypeResponse |
9| EmployeesRequest |
10| EmployeesResponse |
11+-------------------------+
12
13proto.employee.EmployeeService@127.0.0.1:50051> desc EmployeeRequest
14+-------+------------+----------+
15| FIELD | TYPE | REPEATED |
16+-------+------------+----------+
17| id | TYPE_INT64 | false |
18+-------+------------+----------+
CLIモード
今度は同じようにCLIモードで実行していきます。
CLIの場合はevans cli [package].[service].[rpc method]のフォーマットで実行するメソッドを指定します。
例えば全従業員情報を取得する場合はこのようになります。
1echo '{}' | evans -r cli proto.employee.EmployeeService.Employees
2{
3 "employees": [
4 {
5 "age": 20,
6 "id": "1",
7 "name": "Yamada"
8 },
9 {
10 "age": 25,
11 "id": "2",
12 "name": "Suzuki",
13 "type": "PartTime"
14 },
15 {
16 "age": 45,
17 "id": "3",
18 "name": "Sasaki"
19 }
20 ]
21}
もし引数が必要なAPIの場合はechoとパイプを使って渡すことが出来ます。
1echo '{"id": 1}' | evans -r cli proto.employee.EmployeeService.Employee
2{
3 "employee": {
4 "age": 20,
5 "id": "1",
6 "name": "Yamada"
7 }
8}
これでモード別の動作確認は以上となります。
さいごに
今回はEvansというgRPCクライアントツールを使ってgRPCのAPIを動かしてみることができました。
REPLモードとCLIモードを使ってみた感想としては、どちらを使うかは一長一短あるためケースバイケースかなと思いました。
例えばPRを出してレビュアーに動作確認をして欲しい場合は、CLIモード用にコマンドを準備してあげた方がより早く確認することができるかと思いますし、自分で開発中に動かすのであればREPLモードの方が柔軟で楽に確認ができるため状況に応じて使い分けたらいいかと思います。
ぜひEvansを使ってgRPC開発を楽しんでください!
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
「好きを仕事にするエンジニア集団」の(株)ライトコードです! ライトコードは、福岡、東京、大阪、名古屋の4拠点で事業展開するIT企業です。 現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。 いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。 システム開発依頼・お見積もり大歓迎! また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」を積極採用中です! インターンや新卒採用も行っております。 以下よりご応募をお待ちしております! https://rightcode.co.jp/recruit