- 記事作成日:2022/12/01
情報
名前 | URL |
---|---|
Github | https://github.com/bufbuild/connect-go |
公式サイト | https://connect.build/docs/introduction |
デモサイト | https://connect.build/ |
開発母体 | Buf |
version | 1.3.0 |
言語 | Go |
価格 | 無料 |
ライセンス | Apache-2.0 license |
何ができるもの?
Go で gRPC / gRPC-web / connect(独自プロトコル) が簡単に使えるライブラリ
使い方
❯ mkdir connect-go-example ❯ cd connect-go-example ❯ go mod init example ❯ go install github.com/bufbuild/buf/cmd/buf@latest ❯ go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest ❯ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest ❯ go install github.com/bufbuild/connect-go/cmd/protoc-gen-connect-go@latest
❯ mkdir -p greet/v1 ❯ touch greet/v1/greet.proto ❯ cat << EOF > greet/v1/greet.proto heredoc> syntax = "proto3"; package greet.v1; option go_package = "example/gen/greet/v1;greetv1"; message GreetRequest { string name = 1; } message GreetResponse { string greeting = 1; } service GreetService { rpc Greet(GreetRequest) returns (GreetResponse) {} } heredoc> EOF ❯ cat << EOF > buf.gen.yaml version: v1 plugins: - name: go out: gen opt: paths=source_relative - name: connect-go out: gen opt: paths=source_relative EOF ❯ buf lint ❯ buf generate . ├── buf.gen.yaml ├── gen │ └── greet │ └── v1 │ ├── greet.pb.go │ └── greetv1connect │ └── greet.connect.go ├── go.mod └── greet └── v1 └── greet.proto
greet.pb.go
: protoc-gen-go による proto 定義を Go コードにしたものgreet.connect.go
: protoc-gen-connect-go による proto 定義を HTTP Handler にしたもの
サーバ実装コードの追加
❯ cat << EOF > cmd/server/main.go heredoc> >.... "log" "net/http" "github.com/bufbuild/connect-go" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" greetv1 "example/gen/greet/v1" // generated by protoc-gen-go "example/gen/greet/v1/greetv1connect" // generated by protoc-gen-connect-go ) type GreetServer struct{} func (s *GreetServer) Greet( ctx context.Context, req *connect.Request[greetv1.GreetRequest], ) (*connect.Response[greetv1.GreetResponse], error) { log.Println("Request headers: ", req.Header()) res := connect.NewResponse(&greetv1.GreetResponse{ Greeting: fmt.Sprintf("Hello, %s!", req.Msg.Name), }) res.Header().Set("Greet-Version", "v1") return res, nil } func main() { greeter := &GreetServer{} mux := http.NewServeMux() path, handler := greetv1connect.NewGreetServiceHandler(greeter) mux.Handle(path, handler) http.ListenAndServe( "localhost:8080", // Use h2c so we can serve HTTP/2 without TLS. h2c.NewHandler(mux, &http2.Server{}), ) } heredoc> EOF
確認
❯ curl --header "Content-Type: application/json" --data '{"name": "Jane"}' http://localhost:8081/greet.v1.GreetService/Greet {"greeting":"Hello, Jane!"}
利用シーン
- Go で grpc をつかいたけど、grpc-go は見通し悪いなあという時。
- シンプルにやりたい時
登場背景
by DeepL
gRPC は、その発表以来 7 年間に渡り、Protobuf RPC に待望のコンセンサスをもたらしてきました。競合する、相互に互換性のない趣味のプロジェクトのスープから出発して、gRPC チームは、共通のプロトコルの周りにコミュニティを結集し、多くの開発者に RPC スタイルの API を紹介し、Google 以外の Protobuf の人気を牽引してきました。彼らのたゆまぬ努力のおかげで、私たちは Protobuf で API を指定し、gRPC で実装し、ほとんどの言語が互換性のあるクライアント ライブラリを持っていると確信できるようになりました。
概念的には、gRPC プロトコルは HTTPに Protobuf でエンコードされたボディとメタデータを追加したものです。この単純な前提にもかかわらず、このプロトコルと今日の gRPC ライブラリは、非常に複雑化した最大公約数的な設計理念を共有しています。gRPC は、生産システムをシンプルで安定したものにするのではなく、開発、配備、デバッグ、保守を過度に複雑にしています。
例として、GoogleのgRPCのGoでの実装を考えてみましょう。
コメントを除くと、grpc-goは13万行の手書きのコードです。何十ものサブパッケージがあり、100近い設定オプションがあり、特注の名前解決とロードバランシングメカニズムがあります。また、膨大な量のコードがあるため、微妙なバグや リソースリークも避けられません。Go標準ライブラリのnet/httpを使用するのではなく、grpc-goはHTTP/2の独自の実装を使用します。これは Go の HTTP エコシステムの残りの部分と互換性がないので、他の HTTP トラフィックと一緒に gRPC リクエストをきれいに提供することができず、ほとんどのサードパーティ パッケージを使用することができません。
gRPCプロトコルはHTTP/2やTrailerをエンドツーエンドでサポートする必要があり、Webブラウザのような一般的なHTTPクライアントをサポートするには、精巧な翻訳プロキシが必要です。不明瞭な HTTP 機能を使用することに加え、gRPC プロトコルはデバッグが困難です。JSON サポートを有効にしても、単純なリクエストとレスポンスの RPC は、気になる JSON とバイナリー・フレームデータを混在させます。curl | jqや Chrome のネットワーク インスペクタを忘れてください - 利用可能なツールはすべて未熟で gRPC 固有のものです。
ポリシーとして、grpc-goはセマンティックバージョニングに従いません。リリースノートには、"動作の変更 "のための特別なセクションさえ含まれています。過去 1 年間に少なくとも 4 回のリリースで後方互換性が破られ、(etcd を含む)著名な gRPC ユーザは、しばしば一度に数ヶ月間アップデートすることができない状況にあります。
grpc-goのオープンソースコミュニティとGoogleの内部ユーザのニーズのバランスをとることは難しく、ありがたい仕事です。そして、おそらくその幅広い機能とオプションは、Google社内で採用されるために必要なものでしょう。しかし、それ以外のユーザーにとっては、grpc-goの複雑さと不安定さは、我々のコアビジネスから目をそらす不快なものでしかないのです。
気にすること
- 利用者数と開発者数にだいぶ開きがあるので connect を使う場合はそれなりの覚悟が必要。
- ただコード量も少なく見通しも良いので、そんなに困ることは少なそう。(HTTP/2の実装がないのがいい)
- まだ対応している言語が少ない