当我们在使用grpc来提供服务的时候,不免会返回某些错误的信息,grpc为我们提供了定义好的错误码,错误码也非常有限。
以 服务端:go 客户端:python 为例
服务端返回错误信息
return status.Errorf(codes.InvalidArgument,"invalid args: %v" +err)
客户端解析错误信息
- # 1、一般返回的是服务端自定义字符串信息
- e.details()
- # 2、一般是grpc的状态码信息
- status_code = e.code()
- status_code.name # 对应状态码名字(string)
- status_code.value # 对应状态码(int)
grpc为我们提供了16种“开箱即用”的状态码

但是往往我们需要的错误信息是与我们的系统数据相关:所以如何实现扩展呢
1、通过自定义状态码来实现?
- //方式一
- return status.Error(codes.Code(5200), "create failed ")
-
-
- //方式二
- const(
- UserNotExist codes.Code = 5200
- )
- return status.Error(UserNotExist, "create failed ")
实际上 ,客户端接收error时,code信息是2,unknown(这是因为我们自定义的状态码并不存在于grpc约定好的错误码信息中)
2、通过定义proto的message来实现?
Google 基于自身业务, 有了一套错误扩展 https://cloud.google.com/apis/design/errors#error_model, 简单来说就是自己定义了一个 protobuf 错误消息类型:
- // The `Status` type defines a logical error model that is suitable for
- // different programming environments, including REST APIs and RPC APIs.
- message Status {
- // A simple error code that can be easily handled by the client. The
- // actual error code is defined by `google.rpc.Code`.
- int32 code = 1;
-
- // A developer-facing human-readable error message in English. It should
- // both explain the error and offer an actionable resolution to it.
- string message = 2;
-
- // Additional error information that the client code can use to handle
- // the error, such as retry info or a help link.
- repeated google.protobuf.Any details = 3;
- }
此段代码转自:gRPC 扩展错误处理 - 墨天轮 (modb.pro)
那么问题来了, 如何传递这个非标准的错误扩展消息呢? 答案是放在 trailing response metadata
中, key 为 grpc-status-details-bin
此方法搭配 status.Details();但我没有试验成功
s, _ := status.Newf(codes.InvalidArgument, "invalid input").WithDetails(&Status)
这个方法还能将具体的proto字段指定出来并增加描述
- s, _ := status.Newf(codes.InvalidArgument, "invalid input").WithDetails(&errdetails.BadRequest{
- FieldViolations: []*errdetails.BadRequest_FieldViolation{
- {
- Field: "SomeRequest.email_address",
- Description: "INVALID_EMAIL_ADDRESS",
- },
- {
- Field: "SomeRequest.username",
- Description: "INVALID_USER_NAME",
- },
- },
- })
-
- return s.Err()