web-dev-qa-db-ja.com

gRPCでの豊富なエラー処理のパターン

GRPCを使用してエラーに関する詳細をクライアントに送信するパターンは何ですか?

たとえば、メッセージを送信するユーザーを登録するためのフォームがあるとします

message RegisterUser {
  string email = 1;
  string password = 2;
}

電子メールは適切にフォーマットされ、一意である必要があり、パスワードは少なくとも8文字の長さが必要です。

JSON APIを作成している場合、次の本文で400エラーを返します。

{
  "errors": [{
    "field": "email",
    "message": "Email does not have proper format."
   }, {
     "field": "password",
     "message": "Password must be at least 8 characters."
   }],
}

クライアントはユーザーにNiceエラーメッセージを提供することができます(つまり、パスワードフィールドを強調表示し、入力に何か問題があることをユーザーに明確に伝えることによって)。

GRPCで同様のことを行う方法はありますか?ほとんどのクライアント言語では、エラーが発生すると例外がスローされ、応答を取得する方法はないようです。

たとえば、次のようなものが欲しい

message ValidationError {
  string field = 1;
  string message = 2;
}

message RegisterUserResponse {
  repeated ValidationError validation_errors = 1;
  ...
}

または類似。

17
mindvirus

応答メタデータに追加のエラーの詳細を含めます。ただし、有用なステータスコードとメッセージを必ず提供してください。この場合、RegisterUserResponseをメタデータに追加できます。

GRPC Javaでは、次のようになります。

Metadata.Key<RegisterUserResponse> REGISTER_USER_RESPONSE_KEY =
    ProtoUtils.keyForProto(RegisterUserResponse.getDefaultInstance());
...
Metadata metadata = new Metadata();
metadata.put(REGISTER_USER_RESPONSE_KEY, registerUserResponse);
responseObserver.onError(
    Status.INVALID_ARGUMENT.withDescription("Email or password malformed")
      .asRuntimeException(metadata));

別のオプションは google.rpc.Status protoAnyに追加のdetailsが含まれます。型を処理するためのサポートが各言語に提供されます。 Javaでは、次のようになります。

// This is com.google.rpc.Status, not io.grpc.Status
Status status = Status.newBuilder()
    .setCode(Code.INVALID_ARGUMENT.getNumber())
    .setMessage("Email or password malformed")
    .addDetails(Any.pack(registerUserResponse))
    .build();
responseObserver.onError(StatusProto.toStatusRuntimeException(status));

google.rpc.Statusは、エラーの詳細を1つのユニットとして渡すことができるため、一部の言語では簡潔です。また、応答のどの部分がエラー関連であるかを明確にします。通信中、メタデータを使用して追加情報を渡します。

error_details.proto にも興味があるかもしれません。これにはいくつかの一般的なタイプのエラーが含まれています。

I このトピックについて説明しました CloudNativeCon中。 YouTubeでスライドとリンクされた記録を確認できます。

25
Eric Anderson