こちらは TVer Advent Calendar 2024 の2日目の記事です。
1日目の記事は@ukitakaさんのTVerにおける技術統括事務局の取り組みでした。
趣味で開発しているWebサービスでconnect-goを利用しています。
connect-goはgRPC, gRPC-Web, Connectと3つのプロトコルに対応しています。
特にConnectプロトコルを利用すると、Webブラウザからでもenvoyなどのプロキシサーバー不要でprotobufからコード生成した型を利用したRPCメソッド呼び出しができるため大変便利です。
ただキャッシュの面で困るケースがあるため、その回避策を試してみます。
Connectプロトコルを使った通信
まずは素直に公式ドキュメントのGetting started | Connectに従ってサンプル実装をつくります。
Connectプロトコルを使ったAPIサーバーはHTTP POST形式でリクエストができます。
> curl \ --header "Content-Type: application/json" \ --data '{"name": "Jane"}' \ http://localhost:8080/greet.v1.GreetService/Greet {"greeting":"Hello, Jane!"} > curl \ --header "Content-Type: application/json" \ --data '{"name": "Emma"}' \ http://localhost:8080/greet.v1.GreetService/Greet {"greeting":"Hello, Emma!"}
ところがパラメータがリクエストbodyに含まれるため、動的なAPI(今回は名前がパラメータ)の場合
CDNを使ってAPIレスポンスをキャッシュしたいケースで困ります。
ConnectプロトコルのHTTP GET利用モード
それを回避するためConnectにはHTTP GETなリクエストでRPCメソッドを呼び出す機能が存在します。
この機能を有効にすることで、リクエストパラメータがURLのクエリパラメータとして埋め込まれHTTP GETリクエストが発行されます。
今回の例ではGoのクライアントを使用しています。
protoファイルのrpcメソッドにオプションを追加
service GreetService { rpc Greet(GreetRequest) returns (GreetResponse) { option idempotency_level = NO_SIDE_EFFECTS; } }
Connect Clientにオプションを追加。
client := greetv1connect.NewGreetServiceClient( http.DefaultClient, "http://localhost:8080", connect.WithHTTPGet(), )
この状態でサーバーのプロセスを起動し、クライアントからAPIリクエストしてみます。
> go run cmd/client/main.go 2024/11/17 16:10:12 Hello, Jane! # サーバーのログ time=2024-11-17T16:09:27.878+09:00 level=INFO msg=request req.addr=127.0.0.1:50027 req.protocol=connect req.method=GET req.procedure=/greet.v1.GreetService/Greet req.query="base64=1&connect=v1&encoding=proto&message=CgRKYW5l" req.duration=5.625µs
protobufに定義されているパラメータはbase64エンコードされているため、ASCII文字以外のパラメータの送信も可能です。
> go run cmd/client/main.go 2024/11/17 16:11:02 Hello, 👍! # サーバーのログ time=2024-11-17T16:11:02.306+09:00 level=INFO msg=request req.protocol=connect req.method=GET req.procedure=/greet.v1.GreetService/Greet req.query="base64=1&connect=v1&encoding=proto&message=CgTwn5GN" req.duration=5.25µs
最初のサンプルと違い2つのリクエストではURLが異なるため、レスポンスに Cache-Control
ヘッダーを付与すればCDNでのキャッシュが可能です。
まとめ
connect-goを使いつつHTTP GET形式のリクエスト発行ができました。
またこの検証のためにサーバーのアクセスログを出力するmiddlewareも実装しましたが、connect-goのサーバーはnet/httpを利用するためこれまでの資産も使いやすいです。
今回のサンプル実装はこちらのリポジトリに公開しています。
GitHub - takanamito/connect-go-example
明日の記事は@ko-ya346さんの「terraform + github でデータマート管理する」です。