💫
Go言語で書くgRPC テクニック:上級編[ロードバランシングやサーバー制御]
はじめに
gRPCは、高速・軽量な RPCフレームワークで、Go言語との相性が良く、マイクロサービス間の通信やAPIサーバーの実装に最適です。
前回の内容よりgRPCをより高度に活用するためのテクニックを中心に、まとめてみました。
対象読者
- gRPCの基本・中級テクニックを理解しており、より高度な機能を使いたい方
- マイクロサービス間の通信を効率化したい方
- セキュアなgRPC通信を実現したい方
目次
- gRPC Gatewayを使ったREST API化
- gRPC Gatewayの概要
- gRPCサービスをREST APIに変換する方法
- OpenAPI(Swagger)ドキュメントの生成
- gRPCのロードバランシング
- gRPCの名前解決とロードバランサーの仕組み
- ラウンドロビンの実装
- Consulを使ったサービスディスカバリー
- gRPCのセキュリティ(認証と認可)
- SSL / TLSを使った暗号化
- トークンベースの認証(JWT)
- OAuth2を用いた認可
1. gRPC Gatewayを使ったREST API化
gRPC Gatewayを使うことで、gRPCサービスをREST APIとして公開することができます。
1.1 gRPC Gatewayの概要
- gRPCとHTTP / JSONの双方向変換を行うプロキシ。
- Protocol BuffersのコメントをOpenAPI (Swagger) ドキュメントに変換可能。
- gRPCの効率的な通信を維持しながら、RESTクライアントからも利用可能にする。
1.2 gRPCサービスをREST APIに変換する方法
1.protoファイルにHTTPのオプションを追加
syntax = "proto3";
package example;
import "google/api/annotations.proto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloResponse) {
option (google.api.http) = {
get: "/v1/hello/{name}"
};
}
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
2.必要なプラグインをインストール
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
3.gRPC Gatewayのコードを生成
protoc -I. -I$GOPATH/src \
--go_out . --go-grpc_out . \
--grpc-gateway_out . \
--openapiv2_out . \
example.proto
4.Gatewayのサーバーを実装
gateway.go
mux := runtime.NewServeMux()
err := pb.RegisterGreeterHandlerServer(context.Background(), mux, &server{})
if err != nil {
log.Fatalf("Failed to register gateway: %v", err)
}
http.ListenAndServe(":8080", mux)
-
grpc-gateway
がgRPCのエンドポイントをHTTP / JSONとして公開 -
GET /v1/hello/{name}
でgRPCサービスSayHello
を呼び出せる
1.3 OpenAPI (Swagger) ドキュメントの生成
protoc -I. -I$GOPATH/src \
--openapiv2_out . \
example.proto
- 生成された
.swagger.json
をSwagger UIで表示可能
2. gRPC のロードバランシング
2.1 gRPCの名前解決とロードバランサーの仕組み
- gRPCは、ResolverとBalancerの2つのコンポーネントを使用して、ロードバランシングを行う。
- Resolver:名前解決を行う。
- Balancer:複数のサーバーに負荷を分散。
2.2 ラウンドロビンの実装
conn, err := grpc.Dial("dns:///localhost:50051",
grpc.WithDefaultServiceConfig(`{
"loadBalancingConfig": [{"round_robin":{}}]
}`),
grpc.WithInsecure(),
)
-
round_robin
を指定して、ラウンドロビン方式で負荷を分散 -
dns:///
を使用してDNS ベースの名前解決を行う
2.3 Consulを使ったサービスディスカバリー
-
Consul
を使ってサービスディスカバリーとヘルスチェック を実現する -
Consul
にサービスを登録することで、動的にエンドポイントを取得する
3. gRPC のセキュリティ(認証と認可)
3.1 SSL / TLSを使った暗号化
- 自己署名証明書を作成して、SSL / TLSを有効化
creds, err := credentials.NewServerTLSFromFile("server-cert.pem", "server-key.pem")
s := grpc.NewServer(grpc.Creds(creds))
- クライアント側でも
grpc.WithTransportCredentials()
を設定して暗号化通信
3.2 トークンベースの認証(JWT)
-
metadata
を使用して、JWT トークンをヘッダーに含める
md := metadata.New(map[string]string{"authorization": "Bearer <TOKEN>"})
ctx := metadata.NewOutgoingContext(context.Background(), md)
- サーバー側でJWTの検証を行い、認証を実施
3.3 OAuth2 を用いた認可
-
OAuth2
プロバイダーからアクセストークンを取得 -
OAuth2
スコープに基づいて、エンドポイントのアクセス制御を実現 - OpenID Connectを使って、ID トークンの検証 も可能
まとめ
項目 | 説明 |
---|---|
gRPC Gateway | gRPCをREST API化し、Swaggerドキュメントを生成 |
ロードバランシング | ラウンドロビン、Consulを使ったサービスディスカバリー |
セキュリティ | SSL / TLS、JWT、OAuth2による認証と認可 |
gRPC Gatewayを使ったREST API化、ロードバランシング、セキュリティ(認証と認可)など、gRPCをより高度に活用する方法を自分の知識整理も兼ねて開設しました。
gRPCマスターになりたい...
Discussion