gRPC入門してみた

6月 5, 2022

どもども、新しいイヤホン買いました。nothing ear(1)、いい感じです!


本日は聞いたことあるけどずっと触ってこなかったgRPCについに入門してみたので記事にしてみたいと思います。


とは言ってもハンズオン自体は下記記事に沿って行いましたので、ハンズオンも行いたい場合はこちらをご確認ください。チュートリアル用Githubリポジトリまで用意してくれていてすごく親切です。適当なディレクトリを作成してクローンしておいてください!
Go言語+gRPCをはじめから丁寧に解説してみた[ハンズオン]


本記事は学んだ上での知識整理として書いてますのでその点ご理解ください。

そもそもgRPCって?

Google(g)によって作成された RPC フレームワークで gRPC という名前みたいですね。


RPC とは Remote Procedure Call の略でネットワークを通して他の端末のプログラムの呼び出し、実行を行うための方法の一つです。


これだけ聞くと「RESTとなにが違うの?」となりそうです。(かくいう筆者もそう思っていました)


確かに役割としては同等のもですが、考え方が異なります。


RPC は関数・メソッドを呼び出すのに対し、REST はリソース(オブジェクト)を操作します。


RESTはリソース志向であるためURIからバージョンや用途、操作条件が予測可能です。(/v1/search/user など)

さらにHTTPメソッドに操作が統一されているため、操作とメソッドをリンクして考えることができます。(GET:取得、DELETE:削除 など)


RPC では関数・メソッドが直接エンドポイントになるため機能追加が用意です。また、すべて POST で呼び出すことができるためとてもシンプルです。

gRPC はRPCによりやりとりされるデータをシリアル化するこで SSL/TLS 化してくれます。また、データがシリアル化されていることにより容量が小さくなり、効率的な転送を行うことができます。現在、RPC の利用はこの gRPC が前提になっていると言えそうです。

gRPCを利用したメソッドの呼び出し

それでは、実際に gRPC を利用したデータのやり取りを行うコードをみていきましょう。


server.goは待ち受けるwebサーバを立ち上げるコードです。下記の部分に注目してください。

grpcServer := grpc.NewServer()

新規 gRPC サーバを作成してTCP接続を受け付けています。


次に .proto ファイルについてみていきましょう。

gRPCではProtocol Buffersのフォーマットにシリアライズしてデータをやり取りします。Protocol Buffersの一番の特徴は.protoファイルというIDL(インターフェース記述言語)です。.protoファイルを書いて、コンパイラを実行すると任意の言語のサーバー/クライアント用コードを生成してくれます。とても便利。


実際にチュートリアル同様下記のような呼び出すメソッド(SayHello)とレスポンス(Message)を指定した .proto ファイルを作成し

syntax = "proto3";
package chat;

message Message {
  string body = 1;
}

service ChatService {
  rpc SayHello(Message) returns (Message) {}
}

protoc コマンドで Go用のgRPC コード(chat/chat.pb.go)を自動生成できます。

protoc --go_out=plugins=grpc:chat chat.proto

server.go では下記のように Chat service を登録しておきます。

    s := chat.Server{}

    grpcServer := grpc.NewServer()

    chat.RegisterChatServiceServer(grpcServer, &s)

Messageを返すSayHello メソッドを実装しているのがチュートリアルの Chat/chat.go になります。クライアントからの入力をロギングし、Hello From the Server! のメッセージボディを Message として返すメソッドです。

func (s *Server) SayHello(ctx context.Context, in *Message) (*Message, error) {
    log.Printf("Receive message body from client: %s", in.Body)
    return &Message{Body: "Hello From the Server!"}, nil
}

これでサーバーからメソッドを呼び出すところまで実装できました。では gRPC サーバを起動しておきましょう。

go run server.go
Go gRPC Beginners Tutorial!


これで待ち受ける側は完了です。最後にこのメソッドを呼び出すクライアントを実装する必要があります。

それがチュートリアルの client.go です。クローンしたままでは main関数が server.go の main関数と重複して実行できないため、server.goとは別(階層)のディレクトリに移行しておいてください。

下記の部分に注目してください。

c := chat.NewChatServiceClient(conn)
response, err := c.SayHello(context.Background(), &chat.Message{Body: "Hello From Client!"})

gRPC サーバに接続し、Chat Service の中のSayHelloメソッドを “Hello From Client!" というMessageを渡して呼び出していることがわかります。

実行してみると、メソッド側で用意していた Message がレスポンスとして返ってくることがわかります。

go run client.go
2020/04/30 20:10:09 Response from server: Hello From the Server!

サーバ側でもクライアントからメッセージを受け取ったことがわかります。

2022/04/03 17:35:00 Receive message body from client: Hello From Client!

無事 gRPC を利用したデータ通信を確認することができました!

まとめ

今回は、怖くてなかなか手をつけることができなかった gRPC に触れてみました。


実際に触ってみると何も怖いことはなく、ネットワークを通したメソッド呼び出しという単純なフレームワークであることがわかりました。


前述の通り、機能を追加する場合は基本的にはメソッドの追加とクライアント側での呼び出し処理の追加のみで非常に柔軟な拡張ができそうなイメージでした。


今回はチュートリアルに止まりましたが、自作メソッドを呼び出すサーバ、クライアントの作成にもチャレンジしていきたいところです。


最後まで読んでいただきありがとうございました!

本日のおすすめ

Golang

Posted by CY