Skip to content

Latest commit

 

History

History
117 lines (85 loc) · 9.06 KB

README.zh_CN.md

File metadata and controls

117 lines (85 loc) · 9.06 KB

English | 中文

tRPC-Go 错误码定义

前言

所有语言的 tRPC 框架使用统一的错误定义,由错误码 code 和错误描述 msg 组成,这与 Golang 标准库的 error 只有一个字符串不同,所以 tRPC-Go 这边通过 errs 包封装了错误类型,方便用户使用。当用户需要返回错误时,使用 errs.New(code, msg) 来创建错误,而不是使用标准库的 errors.New(msg),如:

func (s *greeterServerImpl) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
    if failed { // 业务逻辑失败
        // 定义错误码,错误信息返回给上游
        return nil, errs.New(int(your-err-code), "your business error message")
    }
    return &pb.HelloRepley{}, nil // 业务逻辑成功
}

错误码类型

tRPC-Go 的错误码分框架错误码 framework,下游框架错误码 callee framework,业务错误码 business

框架错误码

当前自身服务的框架自动返回的错误码,如调用下游服务超时,解包错误等,tRPC 使用的所有框架错误码都定义在 trpc.proto 中。

0~100 为服务端的错误,即当前服务在框架网络层收到请求包之后,进入业务处理函数之前出错,框架会返回错误给上游,业务是无感知的。在上游服务的视角来看就是下游框架错误码

101~200 为客户端的错误,即调用下游服务时出现的客户端层面的错误。

201~400 为流式错误。

框架错误码日志表现如下:

type:framework, code:101, msg:xxx timeout

下游框架错误码

当前服务调用下游时,下游服务(被调服务)的框架返回的错误码,这对于下游服务的业务开发来说可能是无感知的,但很明确就是下游服务返回的错误,跟当前自身服务没有关系,当前服务是正常的,不过一般是由于自己参数错误引起下游出错。 出现这个错误,请根据错误信息检查请求参数并与下游服务联调解决。

一般日志表现如下:

type:callee framework, code:12, msg:rpcname:xxx invalid

业务错误码

当前服务调用下游时,下游服务的业务逻辑通过 errs.New 返回的错误码。注意:该错误类型是下游服务的业务逻辑返回的错误码,是下游服务定义的,具体含义需要查阅下游服务文档或咨询下游服务开发者。

tRPC-Go 推荐:业务错误时,使用 errs.New 来返回业务错误码,而不是在应答包里面自己定义错误码,错误码和应答包是互斥的,所以如果返回了错误,框架会忽略应答包。

建议用户自定义的错误码范围大于 10000。

一般日志表现如下:

type:business, code:10000, msg:xxx fail

错误码定义

注意:以下错误码说的是框架错误码和下游框架错误码。业务错误码是业务服务定义的,具体含义需要查阅下游服务文档或咨询下游服务开发者。错误码只是提供了概括性的错误类型,具体错误原因一定要仔细看错误详细信息。

错误码 含义
0 成功
1 服务端解码错误,一般是上下游服务 pb 字段没有对齐或者没有同步更新,解包失败,上下游服务全部更新到 pb 最新版,保持 pb 同步即可解决
2 服务端编码错误,序列化响应包失败,一般是 pb 字段设置问题,如把不可见字符的二进制数据设置到 string 字段里面了,具体看错误信息
11 服务端没有相应的 service 实现
12 服务端没有相应的接口实现,调用函数填错
21 服务端业务逻辑处理时间过长超时,超过了链路超时时间或者消息超时时间
22 服务端过载,一般是下游服务端使用了过载保护插件
23 请求被服务端限流
24 服务端全链路超时,即上游调用方给的超时时间过短,还来不及进入本服务的业务逻辑
31 服务端系统错误,一般是 panic 引起的错误,大概率是被调服务空指针,数组越界等
41 鉴权不通过
51 请求参数校验不通过
101 请求在客户端调用超时
102 客户端全链路超时,即当前发起 rpc 的超时时间过短,有可能是上游给的超时时间不够,也有可能是前面的 rpc 调用已经耗尽了大部分时间
111 客户端连接错误,一般是下游没有监听该 ip:port,如下游启动失败
121 客户端编码错误,序列化请求包失败
122 客户端解码错误,一般是 pb 没有对齐
123 请求被客户端限流
124 客户端过载错误
131 客户端选 ip 路由错误,一般是服务名填错,或者该服务名下没有可用实例
141 客户端网络错误
151 响应参数校验不通过
161 上游调用方提前取消请求
171 客户端读取帧数据错误
201 服务端流式网络错误
351 客户端流式读取数据失败
999 未明确的错误,一般是下游直接用 Golang 标准库 errors.New(msg) 返回了不带数字的错误了,没有用框架自带的 errs.New(code, msg)

实现

tRPC-Go 中错误结构具体实现如下:

type Error struct {
    Type int    // 错误码类型 1 框架错误码 2 业务错误码 3 下游框架错误码
    Code int32  // 错误码
    Msg  string // 错误信息描述
    Desc string // 错误额外描述,主要用于监控前缀,如 trpc 框架错误为 trpc 前缀,http 协议错误为 http 前缀,用户可以通过实现拦截器捕获该 err 并更改该字段实现上报任意前缀的监控
}

错误处理流程:

  • 当服务端通过 errs.New 返回业务错误时,框架会将该错误填入 trpc 协议头的业务错误 func_ret 字段里。
  • 当服务端通过 errs.NewFrameError 返回框架错误时,框架会将该错误填入 trpc 协议头的框架错误 ret 字段里。
  • 当服务端框架回包时,会判断是否有错误,有错误则会抛弃响应数据包,所以如果返回错误时,不要再试图通过响应包返回数据。
  • 当客户端发起 RPC 调用时,框架需要先执行编码等操作,再把请求发送到下游,如果在发出网络数据之前出错,则直接返回 框架错误 给用户;如果发送请求成功并收到回包,但从回包的协议头中解析出框架错误则返回 下游框架错误,如果解析出业务错误则返回 业务错误