ConnectのGetting startedをやってみる
やってみる
作業リポ
参考
ひとまずインストールした
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 connectrpc.com/connect/cmd/protoc-gen-connect-go@latest
環境変数にパスを追加する
[ -n "$(go env GOBIN)" ] && export PATH="$(go env GOBIN):${PATH}"
[ -n "$(go env GOPATH)" ] && export PATH="$(go env GOPATH)/bin:${PATH}"
-n はシェルスクリプト内で使用される条件テストオプション。具体的には、-n は与えられた文字列が空でない場合に真(true)を返す
Protocol Buffer でサービスを定義する
mkdir -p greet/v1
touch greet/v1/greet.proto
greet/v1/greet.proto 編集する。リクエストとレスポンスとサービスが定義されてるっぽい
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) {}
}
コード生成するのに、Bufというツールを使うらいしい
We're going to generate our code using Buf,
buf mod init
を実行して、buf.yaml
を生成する。
生成した buf.yaml
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
buf.yaml
は lint や依存関係の管理について記述されるファイルらしい。
buf.gen.yaml
に以下の内容を入力して、Bufにどのようにコードを生成するかを指示する。
version: v1
plugins:
- plugin: go
out: gen
opt: paths=source_relative
- plugin: connect-go
out: gen
opt: paths=source_relative
設定ファイルが整ったら、スキーマをリントしてコードを生成することができます。
buf lint
buf generate
buf generate
したら以下のファイルが生成されてた。
gen/greet/v1/greetv1connect/greet.connect.go
gen/greet/v1/greet.pb.go
gen
└── greet
└── v1
├── greet.pb.go
└── greetv1connect
└── greet.connect.go
生成されたコードには、まだGreetのロジックは実装されていない。GreetServiceHandler
インターフェースを満たすように Greet のロジックを実装する。
// GreetServiceHandler is an implementation of the greet.v1.GreetService service.
type GreetServiceHandler interface {
Greet(context.Context, *connect.Request[v1.GreetRequest]) (*connect.Response[v1.GreetResponse], error)
}
`cmd/server/main.go`
package main
import (
"context"
"fmt"
"log"
"net/http"
"connectrpc.com/connect"
"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{}),
)
}
サーバーを起動する。
$ go run ./cmd/server/main.go
リクエストする
curl \
--header "Content-Type: application/json" \
--data '{"name": "Jane"}' \
http://localhost:8080/greet.v1.GreetService/Greet
レスポンス
{"greeting":"Hello, Jane!"}%
buf generate
実行して生成されたクライアントを使ってリクエストすることもできる。
`cmd/client/main.go`
package main
import (
"context"
"log"
"net/http"
greetv1 "example/gen/greet/v1"
"example/gen/greet/v1/greetv1connect"
"connectrpc.com/connect"
)
func main() {
client := greetv1connect.NewGreetServiceClient(
http.DefaultClient,
"http://localhost:8080",
)
res, err := client.Greet(
context.Background(),
connect.NewRequest(&greetv1.GreetRequest{Name: "Jane"}),
)
if err != nil {
log.Println(err)
return
}
log.Println(res.Msg.Greeting)
}
$ go run ./cmd/client/main.go
2023/09/16 17:42:53 Hello, Jane!
コネクトとは?
-
gRPC互換のHTTP APIを構築するライブラリ。短い protocol buffer スキーマを定義して、コード生成して、アプリケーションロジックを実装するだけで、Connect が堅安全のクラアントを生成してくれたり、他にもいろいろ便利なことをやってくれてる。
-
gRPCサーバー/クライアントフレームワーク
3つのプロトコルをサポートしてる
gRPCプロトコル
これは、gRPCエコシステム全体で広く利用されているプロトコルです。connect-goは、他のgRPCの実装と簡単に互換性を持たせることができます。
gRPC-Webプロトコル
これは、特にWebのフロントエンドとバックエンド間の通信を効率的にするために設計されたプロトコルです。connect-goは、特定の中継プロキシを必要とせずに、grpc-webのフロントエンドと連携することができます。
Connectプロトコル
これは新しいプロトコルで、HTTPベースのシンプルな設計になっています。gRPCとgRPC-Webの優れた機能を組み込んでおり、さまざまなシステムや環境で一貫して動作します。
So what?
- 少量のコードで効率的にAPIサーバーを構築できる。
- 特にgRPCやConnectのようなプロトコルを使用すると、多くの通常のRESTfulなサービスで必要な作業(URLの設計やマーシャリングなど)を大幅に減少させることができる。
- このアプローチの利点として、エンドユーザーには、開発者の追加の労力なしで、標準的で安全なクライアントが提供できる。
gRPCとは
gRPCの説明わかりやすい
gRPC純正のgoのライブラリが微妙らしく、connect が登場したっぽい
コード生成される感じが、graphql codegen の server preset と雰囲気似てるなと思った。そもそも gRPCを触ったことがない & つかいどころがよくわからんって感じなので、またいつか触る時が来たら思い出そう。
goでシナリオテストするライブラリ
この記事 gRPC についてわかりやすかった
mapの使いかた