业务异常
业务自定义异常方便用户使用实现了特定接口的 err 来传递业务异常,以便与 RPC 链路异常做区分。RPC 异常通常表示一次 RPC 请求失败,比如超时、熔断、限流,从 RPC 层面是失败的请求, 但业务错误属于业务逻辑层面,在 RPC 层面其实是请求成功。服务监控建议对于 RPC 错误上报为请求失败,而业务层面错误,上报为请求成功,而使用额外的 biz_status_code 字段上报业务异常状态码。该能力对于工程实践具有一定的价值。
BizStatusError 接口定义
内置 BizStatusErrorIface
提供自定义异常接口,框架同时提供默认实现,用户也可以自定义实现。gRPC 用户自定义的 Error 可同时实现 GRPCStatusIface
,以便复用 Status 的 Detail 用于透传更丰富的业务信息。
用户使用
你可以在 server handler 使用 NewBizStatusError
或 NewBizStatusErrorWithExtra
函数构造业务异常并作为err返回。之后在 client 端通过 FromBizStatusError
函数将err转换回 BizStatusErrorIface
来获取需要的异常信息。
用法示例
使用 TTHeader 作为传输协议:
如需额外传递 gRPC Detail,可以使用 NewGRPCBizStatusError
或 NewGRPCBizStatusErrorWithExtra
来构造异常:
注:如无需传递 gRPC Detail,gRPC 用户仍可以使用
NewBizStatusError
或NewBizStatusErrorWithExtra
.
框架实现
依赖传输协议透传自定义异常的错误码和错误信息,Thrift 和 Kitex Protobuf 依赖 TTHeader,Kitex gRPC 依赖 HTTP2。
- Thrift:使用 TTHeader
- Kitex Protobuf:使用 TTHeader
- gRPC:使用 HTTP2 Header
框架处理
TTHeader
新增了三个 string key,分别是 biz-status 、 biz-message 和 biz-extra。
对于服务端,如果用户通过 NewBizStatusError
构造了 error,将 errorCode、message 和 extra 信息分别装填到 biz-status、biz-message 和 biz-extra;
对于调用端,如果 TTHeader 中 biz-status != 0,则构造 BizStatusErrorIface
返回给用户。
Streaming - gRPC
gRPC 的 RPC 异常是通过 HTTP2 Header 传递的,statusCode 和 statusMessage 分别对应 header 中的 grpc-status 和 grpc-message。
为尽量做到前向兼容,同时区分 gRPC 的 RPC 异常,在其现有基础上额外增加 biz-status 和 biz-extra 字段,分别对应于 BizStatusErrorIface
的 errorCode 和 extra,而 message 则复用 grpc-message。
在 server 返回自定义异常时,将 grpc-status 编码为业务异常实现的 GRPCStatusIface
接口中的 statusCode 或 codes.Internal
,同时编码 biz-status。这样,上游收到响应后,发现设置了 biz-status header, 即可将错误转换为 BizStatusErrorIface
返回给 client handler。即使上游不支持自定义异常,也能相对正确地处理 server 返回的 error,只不过丢失了识别业务异常的能力。