実装
サーバーとクライアントの実装を含む、Goaの生成コードを使用したgRPCサービスの実装方法を学ぶ
このガイドでは、Goaが生成したコードを使用してgRPCサービスを実装する方法について説明します。完全なgRPCサービスの作成に関するステップバイステップのガイドについては、gRPCサービスチュートリアルを参照してください。
トランスポートの独立性
Goaの重要な特徴は、ビジネスロジックの実装がトランスポートプロトコルから独立していることです。gen/serviceで生成されるサービスインターフェースはプロトコルに依存しないため、以下が可能です:
- トランスポートの詳細を気にすることなく、コアビジネスロジックの実装に集中できる
- 同じサービス実装で複数のトランスポート(gRPC、HTTPなど)をサポートできる
- トランスポートの懸念事項から切り離してビジネスロジックをテストできる
トランスポート固有のコード(この場合はgRPC)は別個に生成され、サービス実装を特定のプロトコル要件に適応させます。
コード生成の概要
goa genを実行すると、Goaは以下のコンポーネントを生成します:
gen/
├── grpc/
│ ├── pb/ # Protocol Buffer生成コード
│ │ └── service.pb.go
│ ├── client/ # gRPCクライアントコード
│ │ └── client.go
│ └── server/ # gRPCサーバーコード
│ └── server.go
└── service/ # サービスインターフェースと型
└── service.go
これらのコンポーネントの生成と理解に関する詳細な手順については、サービスの実装チュートリアルのセクションを参照してください。
gRPC固有の機能
ストリーミング
gRPCはサーバーサイド、クライアントサイド、双方向ストリーミングをサポートしています。Goaでのストリーミングの実装に関する詳細情報、例、ベストプラクティスについては、専用のストリーミングガイドを参照してください。
ベストプラクティス
エラー処理
gRPC固有のエラーコードを使用し、意味のあるメタデータを含めます:
import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func (s *calculator) Divide(ctx context.Context, p *calc.DividePayload) (*calc.DivideResult, error) {
if p.Divisor == 0 {
return nil, status.Error(codes.InvalidArgument, "ゼロによる除算")
}
quotient := float64(p.Dividend) / float64(p.Divisor)
return &calc.DivideResult{Quotient: quotient}, nil
}
コンテキストの使用
gRPCコンテキストのキャンセルとタイムアウトを処理します:
func (s *calculator) LongOperation(ctx context.Context, p *calc.LongOperationPayload) (*calc.LongOperationResult, error) {
select {
case <-ctx.Done():
return nil, status.Error(codes.Canceled, "操作がキャンセルされました")
case result := <-s.processAsync(p):
return result, nil
}
}
リソース管理
gRPC接続とリソースを適切に管理します:
type grpcServer struct {
server *grpc.Server
lis net.Listener
}
func NewGRPCServer(svc calc.Service) (*grpcServer, error) {
srv := grpc.NewServer()
calcsvr.Register(srv, svc)
lis, err := net.Listen("tcp", ":8080")
if err != nil {
return nil, err
}
return &grpcServer{
server: srv,
lis: lis,
}, nil
}
func (s *grpcServer) Start() error {
return s.server.Serve(s.lis)
}
func (s *grpcServer) Stop() {
s.server.GracefulStop()
s.lis.Close()
}
適切なエラー処理、ロギング、グレースフルシャットダウンを備えたgRPCサーバーのセットアップの完全な例については、チュートリアルのサーバーのセットアップセクションを参照してください。