GoaはgRPCサービスの設計と実装のためのファーストクラスサポートを提供しています。このガイドではGoaでgRPCを使用する際の主要な概念を紹介します。
gRPCは、以下の特徴を持つ高性能なRPC(Remote Procedure Call)フレームワークです:
Goaのg RPCサポートは以下を提供します:
.proto
ファイル)GoaでgRPCサービスを定義する方法を見てみましょう。以下の例は、2つの数値を加算する簡単な計算機サービスを示しています:
var _ = Service("calculator", func() {
// サービスの説明はサービスの目的を文書化するのに役立ちます
Description("計算機サービスは算術演算を実行します")
// このサービスのgRPCトランスポートを有効化し設定します
GRPC(func() {
// このブロックにはタイムアウトやインターセプターなど、
// gRPC固有の設定を含めることができます
})
// gRPCエンドポイントとして公開される"add"メソッドを定義します
Method("add", func() {
// このメソッドの機能を文書化します
Description("2つの数値を加算します")
// 入力メッセージ構造を定義します(クライアントが送信するもの)
// 各Fieldは:位置番号、フィールド名、型を取ります
Payload(func() {
Field(1, "a", Int) // 加算する1つ目の数値
Field(2, "b", Int) // 加算する2つ目の数値
Required("a", "b") // 両方のフィールドは必須です
})
// 出力メッセージ構造を定義します(サーバーが返すもの)
Result(func() {
Field(1, "sum", Int) // a + bの結果
})
})
})
このコードは1つのメソッドを持つ完全なgRPCサービスを定義しています。Field(1, ...)
の数値はメッセージシリアライゼーションに必要なProtocol Bufferのフィールド番号です。
Goaでタイプを定義すると、自動的に対応するProtocol Bufferタイプにマッピングされます。以下がGoaタイプとProtocol Bufferタイプの対応関係です:
Goaタイプ | Protocol Bufferタイプ |
---|---|
Int | int32 |
Int32 | int32 |
Int64 | int64 |
UInt | uint32 |
UInt32 | uint32 |
UInt64 | uint64 |
Float32 | float |
Float64 | double |
String | string |
Boolean | bool |
Bytes | bytes |
ArrayOf | repeated |
MapOf | map |
gRPCは4つの異なる通信パターンをサポートしています。それぞれの例を見てみましょう:
Unary RPC: 最もシンプルなパターン - クライアントが1つのリクエストを送信し、1つのレスポンスを受け取ります
Method("add", func() {
Description("シンプルな加算メソッド - 2つの数値を受け取り、その合計を返します")
Payload(func() {
Field(1, "x", Int, "1つ目の数値")
Field(2, "y", Int, "2つ目の数値")
})
Result(func() {
Field(1, "sum", Int, "xとyの合計")
})
})
サーバーストリーミング: クライアントが1つのリクエストを送信し、時間とともに複数のレスポンスを受け取ります
Method("stream", func() {
Description("指定された開始数値からカウントダウンする数値をストリーミングします")
Payload(func() {
Field(1, "start", Int, "カウントダウンを開始する数値")
})
// StreamingResultはサーバーが複数のレスポンスを送信することを示します
StreamingResult(func() {
Field(1, "count", Int, "カウントダウン中の現在の数値")
})
})
クライアントストリーミング: クライアントが時間とともに複数のリクエストを送信し、サーバーが1つのレスポンスを送信します
Method("collect", func() {
Description("複数の数値を受け取り、その合計を返します")
// StreamingPayloadはクライアントが複数のリクエストを送信することを示します
StreamingPayload(func() {
Field(1, "number", Int, "合計に加算する数値")
})
Result(func() {
Field(1, "total", Int, "受信したすべての数値の合計")
})
})
双方向ストリーミング: クライアントとサーバーの両方が時間とともに複数のメッセージを送信できます
Method("chat", func() {
Description("両サイドがメッセージを送信できる双方向チャット")
StreamingPayload(func() {
Field(1, "message", String, "クライアントからのチャットメッセージ")
})
StreamingResult(func() {
Field(1, "response", String, "サーバーからのチャットメッセージ")
})
})
各パターンは異なるシナリオに適しています:
以下のセクションで詳細な情報を提供しています: