trpc.group/trpc-go/trpc-go@v1.0.3/errs/README.zh_CN.md (about) 1 [English](README.md) | 中文 2 3 # tRPC-Go 错误码定义 4 5 6 ## 前言 7 8 所有语言的 tRPC 框架使用统一的错误定义,由错误码 `code` 和错误描述 `msg` 组成,这与 Golang 标准库的 error 只有一个字符串不同,所以 tRPC-Go 这边通过 errs 包封装了错误类型,方便用户使用。当用户需要返回错误时,使用 `errs.New(code, msg)` 来创建错误,而不是使用标准库的 `errors.New(msg)`,如: 9 10 ```golang 11 func (s *greeterServerImpl) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) { 12 if failed { // 业务逻辑失败 13 // 定义错误码,错误信息返回给上游 14 return nil, errs.New(int(your-err-code), "your business error message") 15 } 16 return &pb.HelloRepley{}, nil // 业务逻辑成功 17 } 18 ``` 19 20 ## 错误码类型 21 22 tRPC-Go 的错误码分框架错误码 `framework`,下游框架错误码 `callee framework`,业务错误码 `business`。 23 24 ### 框架错误码 25 26 当前自身服务的框架自动返回的错误码,如调用下游服务超时,解包错误等,tRPC 使用的所有框架错误码都定义在 [trpc.proto](https://github.com/trpc-group/trpc/blob/main/trpc/trpc.proto) 中。 27 28 0~100 为服务端的错误,即当前服务在**框架网络层收到请求包之后,进入业务处理函数之前**出错,框架会返回错误给上游,业务是无感知的。在上游服务的视角来看就是[下游框架错误码](#下游框架错误码)。 29 30 101~200 为客户端的错误,即调用下游服务时出现的客户端层面的错误。 31 32 201~400 为流式错误。 33 34 框架错误码日志表现如下: 35 36 ```golang 37 type:framework, code:101, msg:xxx timeout 38 ``` 39 40 ### 下游框架错误码 41 42 当前服务调用下游时,下游服务(被调服务)的框架返回的错误码,这对于下游服务的业务开发来说可能是无感知的,但很明确就是下游服务返回的错误,跟当前自身服务没有关系,当前服务是正常的,不过一般是由于自己参数错误引起下游出错。 43 出现这个错误,请根据错误信息检查请求参数并与下游服务联调解决。 44 45 一般日志表现如下: 46 47 ```golang 48 type:callee framework, code:12, msg:rpcname:xxx invalid 49 ``` 50 51 ### 业务错误码 52 53 当前服务调用下游时,下游服务的业务逻辑通过 `errs.New` 返回的错误码。注意:该错误类型是下游服务的业务逻辑返回的错误码,是下游服务定义的,具体含义需要查阅下游服务文档或咨询下游服务开发者。 54 55 tRPC-Go 推荐:业务错误时,使用 `errs.New` 来返回业务错误码,而不是在应答包里面自己定义错误码,错误码和应答包是互斥的,所以如果返回了错误,框架会忽略应答包。 56 57 建议用户自定义的错误码范围大于 10000。 58 59 一般日志表现如下: 60 61 ```golang 62 type:business, code:10000, msg:xxx fail 63 ``` 64 65 ## 错误码定义 66 67 **注意:以下错误码说的是框架错误码和下游框架错误码。业务错误码是业务服务定义的,具体含义需要查阅下游服务文档或咨询下游服务开发者。错误码只是提供了概括性的错误类型,具体错误原因一定要仔细看错误详细信息。** 68 69 | 错误码 | 含义 | 70 | :----: | :------------------------------------------------------------------------------------------------------------------------------- | 71 | 0 | 成功 | 72 | 1 | 服务端解码错误,一般是上下游服务 pb 字段没有对齐或者没有同步更新,解包失败,上下游服务全部更新到 pb 最新版,保持 pb 同步即可解决 | 73 | 2 | 服务端编码错误,序列化响应包失败,一般是 pb 字段设置问题,如把不可见字符的二进制数据设置到 string 字段里面了,具体看错误信息 | 74 | 11 | 服务端没有相应的 service 实现 | 75 | 12 | 服务端没有相应的接口实现,调用函数填错 | 76 | 21 | 服务端业务逻辑处理时间过长超时,超过了链路超时时间或者消息超时时间 | 77 | 22 | 服务端过载,一般是下游服务端使用了过载保护插件 | 78 | 23 | 请求被服务端限流 | 79 | 24 | 服务端全链路超时,即上游调用方给的超时时间过短,还来不及进入本服务的业务逻辑 | 80 | 31 | 服务端系统错误,一般是 panic 引起的错误,大概率是被调服务空指针,数组越界等 | 81 | 41 | 鉴权不通过 | 82 | 51 | 请求参数校验不通过 | 83 | 101 | 请求在客户端调用超时 | 84 | 102 | 客户端全链路超时,即当前发起 rpc 的超时时间过短,有可能是上游给的超时时间不够,也有可能是前面的 rpc 调用已经耗尽了大部分时间 | 85 | 111 | 客户端连接错误,一般是下游没有监听该 ip:port,如下游启动失败 | 86 | 121 | 客户端编码错误,序列化请求包失败 | 87 | 122 | 客户端解码错误,一般是 pb 没有对齐 | 88 | 123 | 请求被客户端限流 | 89 | 124 | 客户端过载错误 | 90 | 131 | 客户端选 ip 路由错误,一般是服务名填错,或者该服务名下没有可用实例 | 91 | 141 | 客户端网络错误 | 92 | 151 | 响应参数校验不通过 | 93 | 161 | 上游调用方提前取消请求 | 94 | 171 | 客户端读取帧数据错误 | 95 | 201 | 服务端流式网络错误 | 96 | 351 | 客户端流式读取数据失败 | 97 | 999 | 未明确的错误,一般是下游直接用 Golang 标准库 `errors.New(msg)` 返回了不带数字的错误了,没有用框架自带的 `errs.New(code, msg)` | 98 99 ## 实现 100 101 tRPC-Go 中错误结构具体实现如下: 102 103 ```golang 104 type Error struct { 105 Type int // 错误码类型 1 框架错误码 2 业务错误码 3 下游框架错误码 106 Code int32 // 错误码 107 Msg string // 错误信息描述 108 Desc string // 错误额外描述,主要用于监控前缀,如 trpc 框架错误为 trpc 前缀,http 协议错误为 http 前缀,用户可以通过实现拦截器捕获该 err 并更改该字段实现上报任意前缀的监控 109 } 110 ``` 111 112 错误处理流程: 113 114 - 当服务端通过 `errs.New` 返回业务错误时,框架会将该错误填入 trpc 协议头的业务错误 `func_ret` 字段里。 115 - 当服务端通过 `errs.NewFrameError` 返回框架错误时,框架会将该错误填入 trpc 协议头的框架错误 `ret` 字段里。 116 - 当服务端框架回包时,会判断是否有错误,有错误则会抛弃响应数据包,所以如果返回错误时,不要再试图通过响应包返回数据。 117 - 当客户端发起 RPC 调用时,框架需要先执行编码等操作,再把请求发送到下游,如果在发出网络数据之前出错,则直接返回 `框架错误` 给用户;如果发送请求成功并收到回包,但从回包的协议头中解析出框架错误则返回 `下游框架错误`,如果解析出业务错误则返回 `业务错误`。