gRPC での呼び出し

このページでは、gRPC を使用して Cloud Run for Anthos サービスを他のサービスと接続する(たとえば、内部のマイクロサービス間でシンプルかつ高パフォーマンスの通信を行う場合など)デベロッパーを対象として Cloud Run for Anthos 固有の情報について詳しく説明します。Cloud Run for Anthos は、単項ストリーミングの gRPC 呼び出しをどちらもサポートしています。

gRPC 単項

単項 RPC 呼び出しでは、クライアントは単一のリクエストをサーバーに送信し、通常の関数呼び出しと同様に単一のレスポンスを受信します。
rpc SayHello(HelloRequest) returns (HelloResponse);

gRPC ストリーミング

gRPC では次のストリーミング オプションを使用できます。サーバー ストリーミング RPC では、クライアントがサーバーにリクエストを送信し、一連のメッセージを含むストリームを受信して読み取ります。クライアントは、受信したストリームをメッセージがなくなるまで読み取ります。

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);

クライアント ストリーミング RPC では、クライアントは、一連のメッセージを書き込み、ストリームでサーバーに送信します。クライアントは、メッセージの書き込みを終了すると、サーバーがレスポンスを返すのを待ちます。

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);

双方向ストリーミング RPC では、クライアントとサーバーが独立して動作する 2 つの読み取り / 書き込みストリームでメッセージを送信します。

rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);

考えられるユースケースには、次のようなものがあります。

  • 内部マイクロサービス間の通信。
  • 高負荷のデータ(gRPC では、プロトコル バッファを使用します。これは REST 呼び出しの最大 7 倍の速度です)。
  • 単純なサービス定義だけが必要で、完全なクライアント ライブラリは作成しないケース。

サービスを gRPC と統合するには:

  • リクエスト メッセージとレスポンスを proto ファイルに定義し、コンパイルします。
  • リクエストを処理してレスポンスを返す gRPC サーバーを作成します。このサーバーは PORT 環境変数をリッスンする必要があります。
  • リクエストを送信し、gRPC サーバーからのレスポンスを処理するクライアントを作成します。
  • 必要に応じて、認証を追加します。
  • サービスをビルドしてデプロイします。

proto ファイルでメッセージを定義してコンパイルする

proto 定義に追加するその他のものや Cloud Run 固有のものはありません。gRPC の他の場合での使用と同様に、サービス定義とデータのシリアル化には gRPC プロトコル バッファを使用します。

gRPC クライアントを作成する

gRPC を使用するクライアントに追加するその他のものや Cloud Run for Anthos 固有のものはありません。クライアント コードのサービス定義と、言語別の gRPC チュートリアルで提示されるサンプル クライアントの使用については、gRPC ドキュメントを参考にしてください。

Cloud Run for Anthos サービスで gRPC リクエストをリッスンする

Cloud Run for Anthos で実行される gRPC サーバーでは、次のコードに示すように、PORT 環境変数で指定されたポートをリッスンする必要があります。これ以外の要件はありません。

Go

func main() {
	log.Printf("grpc-ping: starting server...")

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("Defaulting to port %s", port)
	}

	listener, err := net.Listen("tcp", ":"+port)
	if err != nil {
		log.Fatalf("net.Listen: %v", err)
	}

	grpcServer := grpc.NewServer()
	pb.RegisterPingServiceServer(grpcServer, &pingService{})
	if err = grpcServer.Serve(listener); err != nil {
		log.Fatal(err)
	}
}

サービスへの gRPC 接続を開く

gRPC メッセージを送信できるようにサービスへの gRPC 接続を開くには、ホストドメイン(Cloud Run for Anthos サービスの URL、またはサービスにマッピングされたカスタム ドメイン)を、ポート 443(gRPC で使用されると予想されるポート)とともに指定する必要があります。

Go


import (
	"crypto/tls"
	"crypto/x509"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

// NewConn creates a new gRPC connection.
// host should be of the form domain:port, e.g., example.com:443
func NewConn(host string, insecure bool) (*grpc.ClientConn, error) {
	var opts []grpc.DialOption
	if host != "" {
		opts = append(opts, grpc.WithAuthority(host))
	}

	if insecure {
		opts = append(opts, grpc.WithInsecure())
	} else {
		systemRoots, err := x509.SystemCertPool()
		if err != nil {
			return nil, err
		}
		cred := credentials.NewTLS(&tls.Config{
			RootCAs: systemRoots,
		})
		opts = append(opts, grpc.WithTransportCredentials(cred))
	}

	return grpc.Dial(host, opts...)
}

認証なしで gRPC リクエストを送信する

次のサンプルは、前述のように構成された gRPC 接続を使用して、認証なしでリクエストを送信する方法を示しています。

Go


import (
	"context"
	"time"

	pb "github.com/GoogleCloudPlatform/golang-samples/run/grpc-ping/pkg/api/v1"
	"google.golang.org/grpc"
)

// pingRequest sends a new gRPC ping request to the server configured in the connection.
func pingRequest(conn *grpc.ClientConn, p *pb.Request) (*pb.Response, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	client := pb.NewPingServiceClient(conn)
	return client.Send(ctx, p)
}