エラーハンドリング
gRPCによるエラーの処理方法と、gRPCのエラーコード。
エラーハンドリング
標準エラーモデル
概念ドキュメントや例でもご覧いただいたように、gRPC呼び出しが正常に完了すると、サーバーはクライアントにOKステータスを返します(言語によっては、OKステータスがコードで直接使用される場合とされない場合があります)。しかし、呼び出しが成功しなかった場合はどうなるのでしょうか?
エラーが発生した場合、gRPCは代わりにエラーコードのいずれかを返します。オプションの文字列エラーメッセージは、何が起こったのかについての詳細情報を提供します。エラー情報は、サポートされているすべての言語でgRPCクライアントが利用できます。
リッチなエラーモデル
上記で説明したエラーモデルは、公式のgRPCエラーモデルであり、すべてのgRPCクライアント/サーバーライブラリでサポートされており、gRPCデータ形式(プロトコルバッファかそれ以外か)とは無関係です。これはかなり限定的であり、エラー詳細を通信する機能が含まれていないことに気づかれたかもしれません。
ただし、データ形式としてプロトコルバッファを使用している場合は、Googleによって開発および使用されている、こちらで説明されている、よりリッチなエラーモデルの使用を検討する価値があります。このモデルは、サーバーが返すことができ、クライアントが消費できる追加のエラー詳細を、1つ以上のプロトコルメッセージとして表現できるようにします。また、一般的なニーズ(無効なパラメータ、クォータ違反、スタックトレースなど)をカバーするための、標準的なエラーメッセージタイプのセットを指定しています。この追加のエラー情報のプロトコルバッファバイナリエンコーディングは、レスポンスの末尾メタデータとして提供されます。
このリッチなエラーモデルは、C++、Go、Java、Python、Rubyライブラリですでにサポートされています。また、grpc-webおよびNode.jsライブラリには、それを要求するオープンな課題があります。関心がある場合は、他の言語ライブラリも将来的にサポートを追加する可能性がありますので、GitHubリポジトリを確認してください。ただし、Cで書かれたgrpc-coreライブラリは、データ形式に依存しないように意図されているため、おそらくサポートしないことに注意してください。
プロトコルバッファを使用していない場合でも、同様のアプローチ(エラー詳細を末尾レスポンスメタデータに格納する)を使用できますが、APIで実用的に利用できるように、このデータにアクセスするためのライブラリサポートを見つけるか開発する必要があるでしょう。
ただし、そのような拡張エラーモデルを使用するかどうかを決定する際には、以下のような重要な考慮事項があります。
- 拡張エラーモデルのライブラリ実装は、エラー詳細ペイロードの要件と期待において、言語間で一貫性がない可能性があります。
- 既存のプロキシ、ロガー、その他の標準HTTPリクエストプロセッサは、エラー詳細を可視化できないため、監視やその他の目的でそれらを活用できません。
- トレーラー内の追加のエラー詳細は、ヘッドオブラインブロッキングに干渉し、キャッシュミスが頻繁に発生するため、HTTP/2ヘッダー圧縮の効率を低下させます。
- より大きなエラー詳細ペイロードは、プロトコルの制限(最大ヘッダーサイズなど)に遭遇し、元のエラーを効果的に失う可能性があります。
エラーステータスコード
gRPCでは、ネットワーク障害から認証されていない接続まで、さまざまな状況でエラーが発生し、それぞれが特定のステータスコードに関連付けられています。以下のエラーステータスコードは、すべてのgRPC言語でサポートされています。
一般的なエラー
| ケース | ステータスコード |
|---|---|
| クライアントアプリケーションがリクエストをキャンセルした | GRPC_STATUS_CANCELLED |
| サーバーがステータスを返す前にデッドラインが超過した | GRPC_STATUS_DEADLINE_EXCEEDED |
| サーバー上のメソッドが見つからない | GRPC_STATUS_UNIMPLEMENTED |
| サーバーがシャットダウン中 | GRPC_STATUS_UNAVAILABLE |
| サーバーが例外をスローした(または、ステータスコードを返す以外の方法でRPCを終了した) | GRPC_STATUS_UNKNOWN |
ネットワーク障害
| ケース | ステータスコード |
|---|---|
| デッドライン超過前にデータが送信されなかった。データの一部が送信され、デッドライン超過前に他の障害が検出されなかった場合にも適用される。 | GRPC_STATUS_DEADLINE_EXCEEDED |
| 接続が切断される前に、一部のデータが送信された(例:リクエストメタデータがTCP接続に書き込まれた)。 | GRPC_STATUS_UNAVAILABLE |
プロトコルエラー
| ケース | ステータスコード |
|---|---|
| 圧縮アルゴリズムはサポートされているが、解凍できなかった | GRPC_STATUS_INTERNAL |
| クライアントが使用した圧縮メカニズムをサーバーがサポートしていない | GRPC_STATUS_UNIMPLEMENTED |
| フロー制御リソース制限に達した | GRPC_STATUS_RESOURCE_EXHAUSTED |
| フロー制御プロトコル違反 | GRPC_STATUS_INTERNAL |
| 返されたステータスの解析エラー | GRPC_STATUS_UNKNOWN |
| 認証なし:資格情報がメタデータを取得できなかった | GRPC_STATUS_UNAUTHENTICATED |
| 認証メタデータで無効なホストが設定されている | GRPC_STATUS_UNAUTHENTICATED |
| 返されたプロトコルバッファの解析エラー | GRPC_STATUS_INTERNAL |
| リクエストプロトコルバッファの解析エラー | GRPC_STATUS_INTERNAL |
言語サポート
標準エラーや、よりリッチなエラー詳細を処理する方法について、複数の言語でのコード例が利用可能です。
| 言語 | 例 |
|---|---|
| C++ | C++エラー処理の例 |
| C++エラー詳細の例 | |
| Go | Goエラー処理の例 |
| Goエラー詳細の例 | |
| Java | Javaエラー処理の例 |
| Javaエラー詳細の例 | |
| Node | Nodeエラー処理の例 |
| Python | Pythonエラー詳細の例 |
grpc-errorsリポジトリには、追加のエラー処理例も含まれています。