ProtobufでのgRPCエラーハンドリングパターン
堅牢なgRPCエラーハンドリングのためのprotobufスキーマ設計。ステータスコード、エラー詳細、構造化エラーレスポンス、google.rpc.Statusパターンを解説します。
Services & RPCs
詳細な説明
gRPCサービスのエラー構造化
gRPCはトランスポートレベルのエラーに数値ステータスコードを使用しますが、アプリケーションレベルのエラーにはより豊富な情報が必要です。構造化されたエラー詳細を運ぶprotobufスキーマの設計は、本番サービスのベストプラクティスです。
syntax = "proto3";
package api.v1;
import "google/protobuf/any.proto";
service OrderService {
rpc PlaceOrder(PlaceOrderRequest) returns (PlaceOrderResponse);
rpc CancelOrder(CancelOrderRequest) returns (CancelOrderResponse);
}
message PlaceOrderRequest {
string customer_id = 1;
repeated OrderItem items = 2;
PaymentInfo payment = 3;
}
message PlaceOrderResponse {
oneof result {
Order order = 1;
OrderError error = 2;
}
}
message OrderError {
ErrorCode code = 1;
string message = 2;
repeated FieldViolation field_violations = 3;
map<string, string> metadata = 4;
}
enum ErrorCode {
ERROR_CODE_UNSPECIFIED = 0;
ERROR_CODE_INVALID_INPUT = 1;
ERROR_CODE_OUT_OF_STOCK = 2;
ERROR_CODE_PAYMENT_DECLINED = 3;
ERROR_CODE_CUSTOMER_NOT_FOUND = 4;
ERROR_CODE_RATE_LIMITED = 5;
}
message FieldViolation {
string field = 1;
string description = 2;
}
message OrderItem {
string product_id = 1;
int32 quantity = 2;
}
message PaymentInfo {
string method = 1;
string token = 2;
}
message Order {
string order_id = 1;
string status = 2;
double total = 3;
}
message CancelOrderRequest {
string order_id = 1;
string reason = 2;
}
message CancelOrderResponse {
bool success = 1;
}
エラーハンドリング戦略
戦略1: レスポンス内のoneof(上記) — レスポンスに成功ペイロードまたはエラーオブジェクトのいずれかを含めます。クライアントはどのバリアントが設定されているかを確認します。エラー詳細をインバンドかつ型付きに保ちます。
戦略2: 詳細付きgRPCステータス — gRPCエラーステータスを返し、google.rpc.Statusとgoogle.protobuf.Anyを使用して構造化された詳細メッセージを添付します。Googleのエラーモデルに従います。
戦略3: レスポンス内のエラーフィールド — 通常のレスポンスと並んでオプションのエラーフィールドを含めます。エラーフィールドの存在が失敗を示します。
ベストプラクティス
- ドメイン固有のエラーコードをenumとして定義
- プログラマティックハンドリング用の機械可読エラーコードを含める
- ロギングとデバッグ用の人間可読メッセージを含める
- バリデーションエラーには
FieldViolationを使用して、どのフィールドが無効かを正確に特定 - サービスと並行してエラー型をバージョニングし互換性を維持
ユースケース
入力バリデーション失敗、ビジネスルール違反、マイクロサービス間の運用エラーに対する構造化された解析可能なエラーレスポンスが必要な本番gRPC APIの設計。