🎃
Buf(v2)を用いて複数の.protoファイルを1つの.pbにまとめる
Bufとは
Protobufのビルドを容易にするツール。
protoファイルをprotocでビルドしようとするとオプションまみれになってややこしいため、オプションなどの設定をyamlファイルとして整理できる
公式: https://buf.build/docs/introduction
やりたいこと
異なる複数のディレクトリにある.protoファイルをビルドして単一の.pbファイルにしたい。
その上で、EnvoyのgRPC JSON TranscoderをもちいてREST APIとして公開したい。
背景
以前、Envoyを使ってgRPCサーバをREST APIから呼び出せるようにした。
このとき、http_filters
を以下のように設定した。
http_filters:
- name: envoy.filters.http.grpc_json_transcoder
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder
proto_descriptor: /etc/envoy/protos/articles.api.pb
services:
- articlespb.ArticlesService
(省略)
このとき、articles.api.pbという単一のpbファイルを用意しないといけない。
※以下にある通り、http_filtersを複数用意して対応することはできない。
前提
それぞれの.protoファイルは以下のパスに置かれている。
このとき、個々のファイルの名前はユニークである必要があることに注意
├── articles
│ ├── buf.yaml
│ ├── articlespb
│ │ └── articles.api.proto
├── orders
│ ├── buf.yaml
│ └── orderspb
│ └── orders.api.proto
└── users
│ ├── buf.yaml
└── userspb
└── users.api.proto
手順
1. buf.yamlの作成
プロジェクトのルートディレクトリにbuf.yamlを配置する。
version: v2
lint:
except:
- FIELD_NOT_REQUIRED
- PACKAGE_DIRECTORY_MATCH
- PACKAGE_NO_IMPORT_CYCLE
- PACKAGE_VERSION_SUFFIX
enum_zero_value_suffix: _UNKNOWN
disallow_comment_ignores: true
breaking:
use:
- FILE
except:
- EXTENSION_NO_DELETE
- FIELD_SAME_DEFAULT
deps:
- buf.build/googleapis/googleapis
modules:
- path: articles
- path: users
- path: orders
2. モジュールの依存関係のアップデート
buf mod update
3. 単一の.pbファイルの作成
buf build . -o combined.api.pb
4. envoyの設定ファイルの修正
envoy.yaml
port_value: 51051
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: grpc_json
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
* - match: { prefix: / }
* route: { cluster: grpc, timeout: 60s }
http_filters:
- name: envoy.filters.http.grpc_json_transcoder
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder
proto_descriptor: /etc/envoy/protos/combined.api.pb
services:
+ - articlespb.ArticlesService
+ - userspb.UsersService
+ - orderspb.OrdersService
print_options:
preserve_proto_field_names: false
結果
無事に、localhost:51051/articles, localhost:51051/users, localhost:51051/ordersにアクセスできた。
Discussion