Tech KAYAC Advent Calendar 2023 の18日目の記事です。
カヤックボンドでエンジニアをやっております中野です。
ここ最近golang、gRPCに触れており、Protocol Buffersの環境を整備するにあたって便利だったものを紹介します。
はじめに
Protocol Buffersは、Googleが開発したオープンソースのデータシリアライゼーションフォーマットで、 幅広いサービスで使用されております。protoファイルの管理、使用の設定などが複雑になりがちです。
「buf」は、このプロセスを簡素化し、効率的なワークフローを提供するツールセットです。
bufとは
bufは、Protocol Buffersのファイル管理、依存関係解決、APIの互換性チェックなど容易にするツールです。 これにより、プロジェクトのメンテナンス性が向上します。 また、protoファイルのLinterやFormatterも提供されており、非常に便利です。
導入方法
Bufのインストール
インストールは公式サイトの手順で導入します。
macOSの場合は下記のコマンドでインストールできます。
brew install bufbuild/buf/buf
buf --version 1.28.1
プロジェクトの作成
下記のようなフォルダ構成を用意していきます
bufbuild-sample % tree . ├── buf.gen.yaml ├── buf.work.yaml ├── proto │ ├── buf.lock │ ├── buf.yaml │ └── service │ └── hello.proto
1. モジュール初期化
cd proto
buf mod init
buf mod update
※buf.yamlファイルが生成される。
proto/buf.yaml
version: v1 breaking: use: - FILE lint: use: - DEFAULT
buf.work.yamlファイルの作成
touch buf.work.yaml
buf.work.yaml
# buf.work.yaml version: v1 directories: - proto
2. lint設定の変更
デフォルトのlintのルール設定は、すこし厳しいのでルールをカスタマイズするのをお勧めします。
proto/buf.yaml
version: v1 breaking: #破壊的変更の検知 use: - FILE lint: #lintの設定 use: - DEFAULT # デフォルトルール except: #lintの除外ルール設定 - PACKAGE_VERSION_SUFFIX - PACKAGE_DIRECTORY_MATCH
hello.protoファイルの用意
syntax = "proto3"; package service; option go_package = "bufbuild-sample/pb/service"; // The greeting service definition. service GreeterService { // Sends a greeting rpc SayHello(SayHelloRequest) returns (SayHelloResponse) {} } message SayHelloRequest { string name = 1; } message SayHelloResponse { string name = 1; }
- Linter実行
buf lint
- Formatter実行
buf format -w
3. 設定ファイルの作成&コード自動生成
コードの自動生成の設定ファイルを作成します。
touch proto/buf.gen.yaml
設定を編集して、go用の設定を追加します。
# buf.gen.yaml version: v1 plugins: - plugin: go ## plugin名 out: ./pb ## 生成されるフォルダ opt: ## pluginへのオプション - paths=source_relative - plugin: go-grpc out: ./pb opt: - paths=source_relative
pluginが依存しているパッケージをインスールします。
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
コードを自動生成します。
buf generate
pbフォルダにコードが生成されます
動作確認
動作確認のため下記のような構成になるようにファイルを作成します。
mkdir -p cmd/server service touch cmd/server/main.go service/hello_service.go
bufbuild-sample % tree . ├── cmd │ └── server │ └── main.go ├── go.mod ├── go.sum └── service └── hello_service.go
cmd/server/main.go
package main import ( pb "bufbuild-sample/pb/service" "bufbuild-sample/service" "fmt" "log" "net" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) func main() { if err := run(); err != nil { log.Fatalf("failed to run: %v", err) } } func run() error { // 起動するポート番号を指定 port := 8080 listenPort, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { return err } // gRPCサーバーの生成 server := grpc.NewServer() // サービスをハンドラーに登録 pb.RegisterGreeterServiceServer(server, service.NewGreeterServiceServer()) reflection.Register(server) // サーバーを起動 return server.Serve(listenPort) }
service/hello_service.go
package service import ( "bufbuild-sample/pb/service" "context" ) func NewGreeterServiceServer() *greeterServiceServer { return &greeterServiceServer{} } type greeterServiceServer struct { service.UnsafeGreeterServiceServer } func (svc *greeterServiceServer) SayHello(ctx context.Context, r *service.SayHelloRequest) (*service.SayHelloResponse, error) { name := r.GetName() return &service.SayHelloResponse{Name: "Hello again " + name}, nil }
サーバーを起動する
go run cmd/server/main.go
postmanなどを使用して、リクエストを投げるとレスポンスを確認できます。
おまけ
その他の機能として、Github Actionを使用したCIも提供されています。 PRに対してLinterの実行などが可能です。 buf.build
また、protoファイルにバリデーションルールを記載することも可能です。 ※現在betaリリースとなっております github.com
おわりに
bufの導入により、APIの設計、開発、メンテナンスが容易になります。 Protocol Buffersを検討する際に、導入の候補になってくるようなツールかと思います。 皆様も導入の候補としてご検討ください。
最後まで読んでくれてありがとうございました!