•22 min read

2026年のConnectRPCとgRPC: WebブラウザとGoマイクロサービスのためのエンドツーエンド型安全性

2026年のConnectRPCとgRPC: WebブラウザとGoマイクロサービスのためのエンドツーエンド型安全性

マイクロサービスとリッチクライアントアプリケーションの普及により、堅牢で高性能、かつ型安全な通信プロトコルが不可欠になっています。gRPCはサービス間通信の要石でしたが、そのブラウザ互換性は歴史的に大きな障壁であり、Envoyのようなプロキシや特殊なgRPC-Web実装がしばしば必要でした。Bufが開発したConnectRPCは、gRPC互換でブラウザネイティブ、そしてユビキタスな採用のために設計されたプロトコルを提供することで、これらの制限に対処します。このガイドでは、ConnectRPCと従来のgRPCを分析し、複雑なプロキシなしでWebブラウザ向けにエンドツーエンドの型安全性を備えたデュアルスタックGoマイクロサービスを構築する方法を実演します。

Audio Briefing
0:00 / 0:00

gRPCブラウザの難題

従来のgRPCは、HTTP/2の高度な機能(多重化、サーバープッシュ、バイナリフレーミングなど)とメタデータ用のトレーラーに依存しています。しかし、ブラウザは主にXMLHttpRequestとfetch APIを公開しており、これらはHTTP/1.1中心で、HTTP/2フレームの直接制御やトレーラーへのアクセスができません。この根本的な不一致により、ブラウザベースのgRPCクライアントには変換レイヤーが必要になります。

一般的な解決策は以下の通りです。

  1. gRPC-Web: gRPC呼び出しをブラウザ互換形式(通常はHTTP/1.1とbase64エンコードされたProtobufメッセージ、特定のヘッダー)に変換するプロトコルレイヤーです。これは、gRPC-WebをバックエンドのgRPCに変換するためにプロキシ(Envoy、grpc_web_moduleを備えたNginxなど)を必要とします。
  2. HTTP/JSONゲートウェイ: Protobuf定義からRESTful JSON APIを生成するもので、しばしばgrpc-gatewayを使用します。これはProtobufのバイナリシリアル化とgRPCのストリーミング機能の利点を失い、2つの異なるAPIサーフェスを維持する必要があります。

どちらのアプローチも、運用上のオーバーヘッド、レイテンシの増加、またはgRPCの核となる利点の妥協を招きます。

Advertisement

ConnectRPC: 実用的な進化

ConnectRPC(旧connect-go)は、Protobuf上に構築されたオープンソースのRPCフレームワークです。その主要な革新は、3つの異なるモードをサポートするワイヤプロトコルにあります。

  1. Connect (単項 & ストリーミング): POSTリクエスト、Content-Type: application/proto(またはapplication/json)、およびConnect-Protocol-Version: 1ヘッダーを使用する、シンプルでHTTP/1.1フレンドリーなプロトコルです。メタデータにはHTTPトレーラーを使用しますが、ブラウザ互換性のためにトレーラーがレスポンスボディで送信される「トレーラーエンコード」モードもサポートしています。
  2. gRPC: HTTP/2上の標準gRPCプロトコル。
  3. gRPC-Web: HTTP/1.1上の標準gRPC-Webプロトコル。

このマルチプロトコルサポートにより、単一のConnectRPCサーバーは、ネイティブgRPCクライアント、gRPC-Webクライアント、Connectクライアント(プロキシなしでブラウザネイティブ)を含む、これらのプロトコルのいずれかを使用するクライアントにサービスを提供できます。この柔軟性は、段階的な採用と幅広いクライアント互換性にとって重要です。

ConnectRPCでデュアルスタックGoマイクロサービスを構築する

シンプルなGreeterサービスを実演します。

1. Protobufスキーマを定義する

proto/greeter/v1/greeter.proto:

syntax = "proto3";

package greeter.v1;

option go_package = "github.com/locionic/connectrpc-demo/gen/greeter/v1;greeter_v1";

service GreeterService {
  rpc SayHello(SayHelloRequest) returns (SayHelloResponse) {}
  rpc SayHelloStream(SayHelloRequest) returns (stream SayHelloResponse) {}
}

message SayHelloRequest {
  string name = 1;
}

message SayHelloResponse {
  string message = 1;
}

2. Goサーバーとクライアントスタブを生成する

Protobufのコンパイルとコード生成にはbufを使用します。

buf.gen.yaml:

version: v1
plugins:
  - plugin: buf.build/connectrpc/go:v1.16.2
    out: gen
    opt: paths=source_relative
  - plugin: buf.build/grpc/go:v1.3.0
    out: gen
    opt: paths=source_relative
  - plugin: buf.build/protocolbuffers/go:v1.31.0
    out: gen
    opt: paths=source_relative
  - plugin: buf.build/connectrpc/web:v0.13.0
    out: web/src/gen
    opt:
      - target=ts
      - es_modules=true
      - keep_empty_files=true

buf generateを実行して、GoとTypeScriptのスタブを生成します。

buf generate

これにより、以下が作成されます。

  • gen/greeter/v1/greeter_v1.pb.go: 標準Protobuf Go型。
  • gen/greeter/v1/greeter_v1connect.pb.go: ConnectRPC Goサーバーおよびクライアントスタブ。
  • web/src/gen/greeter/v1/greeter_v1_connect.ts: ConnectRPC TypeScriptクライアントスタブ。
  • web/src/gen/greeter/v1/greeter_v1.ts: Protobuf TypeScript型。

3. Goマイクロサービスを実装する

ConnectRPC Goライブラリ(connect-go)は、サービスを登録し、3つのプロトコル(Connect、gRPC、gRPC-Web)すべてを自動的に処理できるNewServeMuxを提供します。

main.go:

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c" // h2c for HTTP/2 Cleartext
	"golang.org/x/sync/errgroup"

	"github.com/bufbuild/connect-go"
	greeter_v1 "github.com/locionic/connectrpc-demo/gen/greeter/v1"
	"github.com/locionic/connectrpc-demo/gen/greeter/v1/greeter_v1connect"
)

// greeterService implements greeter_v1connect.GreeterServiceHandler.
type greeterService struct{}

// SayHello implements greeter_v1connect.GreeterServiceHandler.
func (s *greeterService) SayHello(
	ctx context.Context,
	req *connect.Request[greeter_v1.SayHelloRequest],
) (*connect.Response[greeter_v1.SayHelloResponse], error) {
	log.Printf("Received SayHello request from %s", req.Peer().Addr)
	log.Printf("Request headers: %v", req.Header())

	response := &greeter_v1.SayHelloResponse{
		Message: fmt.Sprintf("Hello, %s!", req.Msg.Name),
	}
	return connect.NewResponse(response), nil
}

// SayHelloStream implements greeter_v1connect.GreeterServiceHandler for server streaming.
func (s *greeterService) SayHelloStream(
	ctx context.Context,
	req *connect.Request[greeter_v1.SayHelloRequest],
	stream *connect.ServerStream[greeter_v1.SayHelloResponse],
) error {
	log.Printf("Received SayHelloStream request from %s", req.Peer().Addr)
	log.Printf("Request headers: %v", req.Header())

	for i := 0; i < 3; i++ {
		msg := fmt.Sprintf("Stream message %d for %s", i+1, req.Msg.Name)
		if err := stream.Send(&greeter_v1.SayHelloResponse{Message: msg}); err != nil {
			return err
		}
		time.Sleep(500 * time.Millisecond)
	}
	return nil
}

func main() {
	// Create a new ConnectRPC mux.
	// This mux handles routing for Connect, gRPC, and gRPC-Web protocols.
	mux := http.NewServeMux()
	path, handler := greeter_v1connect.NewGreeterServiceHandler(&greeterService{})
	mux.Handle(path, handler)

	// Configure CORS for browser clients.
	// In a production environment, this should be more restrictive.
	corsHandler := func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Access-Control-Allow-Origin", "*") // Allow all origins for demo
			w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
			w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Connect-Protocol-Version, Connect-Accept-Encoding, Connect-Content-Encoding, Grpc-Web, X-Grpc-Web")
			if r.Method == http.MethodOptions {
				w.WriteHeader(http.StatusOK)
				return
			}
			h.ServeHTTP(w, r)
		})
	}

	// Create an HTTP server.
	// h2c.NewHandler enables HTTP/2 Cleartext, allowing clients to speak HTTP/2 without TLS.
	// This is suitable for local development or internal networks where TLS is handled by a proxy.
	// For production internet-facing services, always use TLS (http.Server with TLS config).
	server := &http.Server{
		Addr: ":8080",
		Handler: h2c.NewHandler(corsHandler(mux), &http2.Server{
			// Optional: Configure HTTP/2 server settings
		}),
		ReadHeaderTimeout: 5 * time.Second,
		ReadTimeout:       10 * time.Second,
		WriteTimeout:      10 * time.Second,
		IdleTimeout:       120 * time.Second,
	}

	// Graceful shutdown.
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
	defer stop()

	var g errgroup.Group
	g.Go(func() error {
		log.Printf("Server listening on %s", server.Addr)
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			return fmt.Errorf("server error: %w", err)
		}
		return nil
	})

	// Wait for interrupt signal.
	<-ctx.Done()
	log.Println("Shutting down server...")

	shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := server.Shutdown(shutdownCtx); err != nil {
		log.Fatalf("Server shutdown failed: %v", err)
	}
	log.Println("Server gracefully stopped.")

	if err := g.Wait(); err != nil {
		log.Fatalf("Server encountered an error during shutdown: %v", err)
	}
}

4. TypeScript Webクライアントを実装する

生成されたConnectRPC TypeScriptクライアント(@bufbuild/connect-web)は、サービスと対話するためのクリーンなAPIを提供します。Connectプロトコルを自動的に処理するため、ブラウザネイティブです。

web/src/client.ts:

import { createConnectTransport } from "@bufbuild/connect-web";
import { GreeterService } from "./gen/greeter/v1/greeter_v1_connect";
import { SayHelloRequest } from "./gen/greeter/v1/greeter_v1";

// Configure the Connect transport.
// By default, it uses the Connect protocol.
// For gRPC-Web, you would use `createGrpcWebTransport`.
const transport = createConnectTransport({
  baseUrl: "http://localhost:8080",
});

// Create a client for the GreeterService.
const client = new GreeterService(transport);

async function callSayHello() {
  try {
    const request = new SayHelloRequest({ name: "ConnectRPC Web" });
    const response = await client.sayHello(request);
    console.log("SayHello Response:", response.message);
  } catch (error) {
    console.error("SayHello Error:", error);
  }
}

async function callSayHelloStream() {
  try {
    const request = new SayHelloRequest({ name: "ConnectRPC Stream Client" });
    const stream = client.sayHelloStream(request);

    console.log("Starting SayHelloStream...");
    for await (const response of stream) {
      console.log("SayHelloStream Response:", response.message);
    }
    console.log("SayHelloStream finished.");
  } catch (error) {
    console.error("SayHelloStream Error:", error);
  }
}

// Call the RPCs
callSayHello();
callSayHelloStream();

Webクライアントを実行するには、基本的なHTMLファイルとバンドラー(Webpack、Vite、Parcelなど)が必要です。

web/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ConnectRPC Web Client</title>
</head>
<body>
    <h1>ConnectRPC Web Client Demo</h1>
    <p>Check the browser console for RPC responses.</p>
    <script type="module" src="./src/client.ts"></script>
</body>
</html>

web/package.json:

{
  "name": "connectrpc-web-client",
  "version": "1.0.0",
  "description": "ConnectRPC web client demo",
  "main": "index.js",
  "scripts": {
    "start": "vite",
    "build": "tsc && vite build"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^5.0.2",
    "vite": "^5.0.8"
  },
  "dependencies": {
    "@bufbuild/connect-web": "^0.13.0",
    "@bufbuild/protobuf": "^1.6.0"
  }
}

依存関係をインストールし、Webクライアントを起動します。

cd web
npm install
npm start

http://localhost:5173(またはViteが割り当てるポート)に移動し、コンソール出力を確認します。

アーキテクチャの比較とトレードオフ

機能/側面従来のgRPC (HTTP/2)ConnectRPC (Connectプロトコル)gRPC-Web (ConnectRPCサーバー経由)REST/JSON (例: grpc-gateway)
プロトコルHTTP/2HTTP/1.1 または HTTP/2HTTP/1.1HTTP/1.1 (通常)
ブラウザネイティブいいえ (プロキシ/gRPC-Webが必要)はい (fetch または XHR 経由)いいえ (プロキシまたはサーバーサイドのgRPC-Webサポートが必要)はい
プロキシの必要性はい (ブラウザクライアントの場合、例: Envoy)いいえ (ブラウザクライアントの場合)いいえ (サーバーがConnectRPCのようにgRPC-Webを直接サポートする場合)いいえ
シリアル化Protobuf (バイナリ)Protobuf (バイナリ) または JSONProtobuf (バイナリ、base64エンコード)JSON (テキスト)
ストリーミング双方向、サーバー、クライアントサーバー、クライアント (クライアントストリームは単項に類似)、双方向サーバー、クライアント (クライアントストリームは単項に類似)ネイティブストリーミングなし (SSE/WebSocketsでシミュレート可能)
ワイヤ効率高 (バイナリ、HTTP/2フレーム)高 (バイナリProtobuf)、中程度 (JSON)中程度 (base64オーバーヘッド)低 (テキストベース、冗長)
型安全性非常に優れている (Protobuf)非常に優れている (Protobuf)非常に優れている (Protobuf)中程度 (OpenAPIのようなスキーマ定義、ただしランタイムチェック)
ツール成熟している (protoc、各種言語プラグイン)非常に優れている (buf、connect-go、connect-webなど)良好 (grpc-webクライアント、Envoy設定)良好 (OpenAPIジェネレーター、grpc-gateway)
複雑さ中程度 (HTTP/2、TLS、Web用プロキシ)低 (HTTP/1.1フレンドリー、Web用プロキシなし)中程度 (gRPC-Webプロトコルの詳細、サーバーサイドサポート)中程度 (ProtobufからHTTP動詞/パスへのマッピング)
レイテンシ低低 (Protobuf)、中程度 (JSON)中程度 (base64エンコード/デコード)中程度 (JSONパース/シリアル化)
バンドルサイズ (TS)grpc-web クライアント + Protobufランタイム@bufbuild/connect-web + @bufbuild/protobufgrpc-web クライアント + ProtobufランタイムN/A (カスタムフェッチ呼び出しまたはOpenAPIクライアント)
ユースケースサービス間、モバイル、高性能デスクトップアプリWebブラウザ、サービス間、モバイル、柔軟なデプロイWebブラウザ (レガシー、またはサーバーがgRPC-Webのみをサポートする場合)パブリックAPI、シンプルなCRUD、幅広いクライアント互換性
Advertisement

シリアル化のレイテンシとバンドルサイズ

シリアル化のレイテンシ

Protobufのバイナリシリアル化は、JSONよりも本質的に効率的です。ConnectRPCはJSONをサポートしていますが、その主な利点はProtobufから得られます。

ベンチマーク(概念的、一般的な知識に基づく): 典型的なメッセージペイロード(例:1KB)の場合:

  • Protobuf (バイナリ): 約10-100マイクロ秒(エンコード/デコード)
  • JSON: 約100-1000マイクロ秒(エンコード/デコード)

この違いは、高スループットまたは大規模なペイロードの場合に顕著になります。ConnectRPCはProtobufの効率を直接活用します。

バンドルサイズ (TypeScriptクライアント)

クライアント側のJavaScriptバンドルサイズは、Webパフォーマンスにとって重要な要素です。

  • @bufbuild/connect-web + @bufbuild/protobuf:

    • @bufbuild/protobuf: 約15KB(ミニファイ + gzip圧縮)- コアProtobufランタイムを提供します。
    • @bufbuild/connect-web: 約10KB(ミニファイ + gzip圧縮)- ConnectRPCトランスポートを提供します。
    • 合計: 約25KB + 生成されたクライアントスタブ(小さなスキーマでは無視できる)。
  • grpc-web クライアント + google-protobuf:

    • google-protobuf: 約20KB(ミニファイ + gzip圧縮)- コアProtobufランタイムを提供します。
    • grpc-web: 約15KB(ミニファイ + gzip圧縮)- gRPC-Webトランスポートを提供します。
    • 合計: 約35KB + 生成されたクライアントスタブ。

ConnectRPCは、最適化されたランタイムとブラウザクライアント向けのよりシンプルなプロトコル処理により、わずかに小さいフットプリントを提供します。REST用のカスタムfetch実装と比較すると、Protobufランタイムはオーバーヘッドを追加しますが、型安全性とシリアル化効率の利点は、複雑なアプリケーションの場合、このオーバーヘッドを上回ることがよくあります。

本番環境での注意点とトラブルシューティング

  1. CORSの問題:

    • 症状: ブラウザクライアントが「Access to fetch has been blocked by CORS policy」エラーで失敗する。
    • 原因: サーバーが適切なAccess-Control-Allow-Origin、Access-Control-Allow-Methods、およびAccess-Control-Allow-Headersヘッダーを送信していない。ConnectRPCとgRPC-Webはカスタムヘッダー(Connect-Protocol-Version、Grpc-Web、X-Grpc-Web)を使用します。
    • 修正: Goサーバーに堅牢なCORSミドルウェアを実装する。OPTIONSプリフライトリクエストが正しく処理されていることを確認する。本番環境では、Access-Control-Allow-Originをクライアントドメインに制限する。
    // Example CORS middleware (more robust than the simple one in main.go)
    func NewCORSHandler(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // Allow specific origins in production
            w.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173") // Or read from config
            w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
            w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Connect-Protocol-Version, Connect-Accept-Encoding, Connect-Content-Encoding, Grpc-Web, X-Grpc-Web, X-User-ID, X-Request-ID") // Add any custom headers
            w.Header().Set("Access-Control-Expose-Headers", "Connect-Protocol-Version, Connect-Accept-Encoding, Connect-Content-Encoding, Grpc-Web, X-Grpc-Web") // Expose headers client needs to read
    
            if r.Method == http.MethodOptions {
                w.WriteHeader(http.StatusOK)
                return
            }
            next.ServeHTTP(w, r)
        })
    }
    // In main: server.Handler = h2c.NewHandler(NewCORSHandler(mux), &http2.Server{})
    
  2. 本番環境でのHTTP/2 Cleartext (h2c):

    • 症状: h2cをインターネットに面したエンドポイントに直接デプロイすると、接続のリセットや不可解なエラーが発生する。
    • 原因: h2cはTLSなしのHTTP/2用です。パブリックインターネットトラフィックはTLS(HTTPS)を使用しなければなりません。ブラウザや多くのプロキシはTLS上のHTTP/2(h2)を期待します。
    • 修正: 本番環境では、http.ServerをTLSConfigで構成するか、TLS終端を処理し、HTTP/2(またはConnect/gRPC-Webの場合はHTTP/1.1)をGoサービスに転送するリバースプロキシ(例:Nginx、Caddy、Envoy)の背後にデプロイする。GoサーバーはプレーンHTTP/2またはHTTP/1.1でリッスンする必要があります。
    // Production server with TLS (example)
    // server := &http.Server{
    //     Addr: ":8443",
    //     Handler: corsHandler(mux), // No h2c.NewHandler needed if TLS is configured
    //     TLSConfig: &tls.Config{
    //         MinVersion: tls.VersionTLS12,
    //         // ... other TLS settings
    //     },
    // }
    // log.Fatal(server.ListenAndServeTLS("server.crt", "server.key"))
    
  3. プロキシによるストリーミングの問題:

    • 症状: プロキシが関与すると、サーバーサイドストリーミングまたは双方向ストリーミングが失敗したりハングしたりする。
    • 原因: 一部のプロキシ(特に古いものや誤って設定されたもの)は、応答をバッファリングしたり、接続を時期尚早に終了させたり、HTTP/2ストリームのセマンティクスを正しく処理しなかったりする可能性があります。
    • 修正: プロキシがHTTP/2パススルー用に構成されているか、gRPC/ConnectRPCを明示的に認識していることを確認する。Nginxの場合、grpc_passを使用し、ストリーミングエンドポイントにproxy_buffering off;を確保する。ConnectRPCのConnectプロトコルの場合、特にトレーラーエンコードされた応答の場合、プロキシが応答ボディをバッファリングしないことを確認する。
  4. Protobufバージョンの不一致:

    • 症状: デシリアライズエラー、予期しないフィールド値、またはunknown field警告。
    • 原因: クライアントとサーバーが異なるバージョンのProtobufスキーマまたは生成されたコードを使用している。これは、ローリングデプロイ中や、クライアントとサーバーが異なるコードベースからデプロイされた場合に発生する可能性があります。
    • 修正: 厳密なスキーマバージョン管理を実装する。buf破壊的変更検出を使用する。アトミックなデプロイまたは短期間の後方/前方互換性を確保する。デバッグのためにサーバーで不明なフィールドをログに記録する。
  5. Connect-Accept-Encodingヘッダー:

    • 症状: クライアントが圧縮を期待しているのに非圧縮応答を受け取る、またはその逆。
    • 原因: Connect-Accept-Encodingヘッダー(またはgRPCの場合はgrpc-accept-encoding)は、サポートされている圧縮アルゴリズムを示します。サーバーがクライアントの優先エンコーディングをサポートしない場合、またはその逆の場合、非圧縮にフォールバックします。
    • 修正: クライアントとサーバーの両方が共通の圧縮アルゴリズム(例:gzip、zstd)をサポートするように構成されていることを確認する。ConnectRPCクライアントとサーバーはこれを自動的に処理しますが、カスタムインターセプターやプロキシ構成が干渉する可能性があります。

よくある質問

  1. ConnectRPCはWebアプリケーションのRESTを完全に置き換えることができますか? はい、エンドツーエンドの型安全性、パフォーマンス、ストリーミング機能が最重要視されるアプリケーションでは、ConnectRPCはRESTの優れた代替手段です。統一されたAPIサーフェスを提供し、個別のRESTおよびgRPC APIを維持する必要がなくなります。シンプルなCRUD操作や、幅広い互換性と人間が読めるJSONが優先されるパブリックAPIの場合、RESTが依然として検討される可能性があります。

  2. ConnectRPCは認証と認可をどのように処理しますか? ConnectRPCは、標準のHTTP認証メカニズムとシームレスに統合されます。JWTやAPIキーにはHTTPヘッダー(例:Authorization: Bearer <token>)を使用できます。サーバー側では、ConnectRPCハンドラーをミドルウェアでラップして、Goのhttp.Handlerと同様に認証と認可のチェックを実行できます。connect-goライブラリは、この目的のためにconnect.WithInterceptorを提供します。

    // Example ConnectRPC interceptor for authentication
    func AuthInterceptor() connect.Interceptor {
        return connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
            return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
                authHeader := req.Header().Get("Authorization")
                if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") {
                    return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("missing or invalid authorization header"))
                }
                token := strings.TrimPrefix(authHeader, "Bearer ")
                // Validate token, extract user info, and add to context
                // For demo:
                if token != "valid-token" {
                    return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("invalid token"))
                }
                ctx = context.WithValue(ctx, "userID", "user123") // Store user ID in context
                return next(ctx, req)
            }
        })
    }
    // In main: path, handler := greeter_v1connect.NewGreeterServiceHandler(&greeterService{}, connect.WithInterceptors(AuthInterceptor()))
    
  3. 可観測性(ロギング、トレーシング、メトリクス)についてはどうですか? ConnectRPCは標準HTTP上に構築されているため、既存の可観測性ツールとよく統合されます。

    • ロギング: サーバーサイドハンドラーはリクエストとレスポンスをログに記録できます。クライアントサイドでは、トランスポートをラップできます。
    • トレーシング: connect-goとconnect-webはOpenTelemetryをサポートしています。サーバーでconnect.WithTracing()を、クライアントでcreateConnectTransportをtraceオプションで構成することで、分散トレーシングをすぐに利用できます。
    • メトリクス: 標準のHTTPメトリクス(リクエスト数、レイテンシ、エラー率)はミドルウェアによって収集できます。ConnectRPCはRPC呼び出しに特化したメトリクスも公開します。
  4. ConnectRPCを既存のgRPCサービスで使用できますか? はい。ConnectRPCサーバーはgRPCサーバーとして機能できるため、既存のgRPCクライアント(例:grpc-go、grpc-java)はHTTP/2経由で直接通信できます。逆に、ConnectRPCクライアントは、既存のgRPCサーバーにgRPCプロトコルで話すように構成できます。この相互運用性は大きな強みであり、段階的な移行や混合環境を可能にします。

    // Example: ConnectRPC client talking to a traditional gRPC server
    import { createGrpcTransport } from "@bufbuild/connect-web"; // Note: createGrpcTransport, not createConnectTransport
    
    const grpcTransport = createGrpcTransport({
      baseUrl: "http://localhost:8080", // Assuming gRPC server on 8080
      // For gRPC-Web, you'd use createGrpcWebTransport
    });
    const grpcClient = new GreeterService(grpcTransport);
    

結論

ConnectRPCは、特にWebブラウザとGoマイクロサービスを含む多言語環境において、RPCフレームワークの重要な進歩を意味します。プロキシなしでネイティブなブラウザ互換性を提供し、gRPCの相互運用性とProtobufの効率を維持することで、アーキテクチャを簡素化し、運用オーバーヘッドを削減し、エンドツーエンドの型安全性を提供します。統一された、高性能で保守可能なAPIレイヤーを目指す新しいプロジェクトや移行にとって、2026年のConnectRPCは魅力的な選択肢です。

Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement