gRPC中丰富错误处理的模式 [英] Pattern for rich error handling in gRPC

查看:526
本文介绍了gRPC中丰富错误处理的模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用gRPC向客户端发送有关错误的更多详细信息的模式是什么?

What is the pattern for sending more details about errors to the client using gRPC?

例如,假设我有一个用于注册用户的表格,该表格发送一条消息

For example, suppose I have a form for registering a user, that sends a message

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

必须正确设置电子邮件的格式和唯一性,并且密码长度必须至少为8个字符.

where the email has to be properly formatted and unique, and the password must be at least 8 characters long.

如果我正在编写JSON API,则会在以下正文中返回400错误:

If I was writing a JSON API, I'd return a 400 error with the following body:

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

并且客户端可以向用户提供不错的错误消息(例如,突出显示密码字段并专门告诉用户输入的内容有误).

and the client could provide nice error messages to the user (i.e. by highlighting the password field and specifically telling the user that there's something wrong with their input to it).

使用gRPC是否可以执行类似的操作?似乎在大多数客户端语言中,错误会导致引发异常,而无法获取响应.

With gRPC is there a way to do something similar? It seems that in most client languages, an error results in an exception being thrown, with no way to grab the response.

例如,我想要类似的东西

For example, I'd like something like

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

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

或类似的

推荐答案

在响应元数据中包括其他错误详细信息.但是,仍然要确保提供有用的状态代码和消息.在这种情况下,您可以将RegisterUserResponse添加到元数据.

Include additional error details in the response Metadata. However, still make sure to provide a useful status code and message. In this case, you can add RegisterUserResponse to the Metadata.

在gRPC Java中,它看起来像:

In gRPC Java, that would look like:

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原型,其中包括用于details的附加Any.每种语言都将提供支持以处理该类型.在Java中,它看起来像:

Another option is to use the google.rpc.Status proto which includes an additional Any for details. Support is coming to each language to handle the type. In Java, it'd look like:

// 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在某些语言中更干净,因为错误详细信息可以作为一个单元传递.它还可以清楚地表明响应的哪些部分与错误相关.在线上,它仍然使用元数据来传递附加信息.

google.rpc.Status is cleaner in some languages as the error details can be passed around as one unit. It also makes it clear what parts of the response are error-related. On-the-wire, it still uses Metadata to pass the additional information.

您可能对 error_details.proto

You may also be interested in error_details.proto which contains some common types of errors.

讨论了此主题.您可以在YouTube上查看幻灯片和链接的录像.

I discussed this topic during CloudNativeCon. You can check out the slides and linked recording on YouTube.

这篇关于gRPC中丰富错误处理的模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆