当我们在使用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()