错误处理
gRPC 如何处理错误,以及 gRPC 错误代码。
错误处理
标准错误模型
正如您在我们的概念文档和示例中所见,当 gRPC 调用成功完成时,服务器会向客户端返回一个 OK 状态(根据所用语言的不同,OK 状态可能会也可能不会直接在您的代码中使用)。但是如果调用不成功会发生什么呢?
如果发生错误,gRPC 会返回其错误状态码之一,并附带一个可选的字符串错误消息,提供有关所发生情况的详细信息。所有受支持语言的 gRPC 客户端均可获取这些错误信息。
更丰富的错误模型
上述错误模型是官方的 gRPC 错误模型,受所有 gRPC 客户端/服务器库支持,并且独立于 gRPC 数据格式(无论是 Protocol Buffers 还是其他格式)。您可能已经注意到,它相当有限,并且不包含传达详细错误信息的能力。
但是,如果您使用 Protocol Buffers 作为数据格式,则可能希望考虑使用 Google 开发并使用的更丰富的错误模型,详见此处。此模型使服务器能够返回,并使客户端能够消费以一个或多个 Protobuf 消息形式表示的额外错误详细信息。它进一步指定了一套标准的错误消息类型,以满足最常见的需求(例如无效参数、配额违规和堆栈跟踪)。此额外错误信息的 Protobuf 二进制编码作为响应中的尾部元数据(trailing metadata)提供。
这种更丰富的错误模型已经得到了 C++、Go、Java、Python 和 Ruby 库的支持,至少 grpc-web 和 Node.js 库也有相关的公开议题要求支持。如果有需求,其他语言库将来可能会添加支持,因此如果您感兴趣,请查看它们的 GitHub 仓库。但请注意,用 C 编写的 grpc-core 库不太可能支持它,因为它是有意保持与数据格式无关的。
如果您不使用 Protocol Buffers,也可以使用类似的方法(将错误详细信息放入尾部响应元数据中),但您可能需要查找或开发相应的库支持来访问这些数据,以便在 API 中实际使用它们。
在决定是否使用这种扩展错误模型时,需要注意一些重要的考量因素,包括:
- 扩展错误模型的库实现,在对错误详细信息负载的要求和期望方面,可能在不同语言间不一致。
- 现有的代理、记录器(logger)和其他标准 HTTP 请求处理器无法查看错误详细信息,因此无法利用它们进行监控或其他目的。
- 尾部元数据中额外的错误详细信息会干扰队头阻塞(head-of-line blocking),并且由于缓存未命中更频繁,会降低 HTTP/2 标头压缩效率。
- 较大的错误详细信息负载可能会遇到协议限制(如最大标头大小),从而导致丢失原始错误。
错误状态码
gRPC 在各种情况下都会引发错误,从网络故障到未经身份验证的连接,每种情况都关联特定的状态码。以下错误状态码在所有 gRPC 语言中均受支持。
一般错误
| 情况 | 状态码 |
|---|---|
| 客户端应用程序取消了请求 | GRPC_STATUS_CANCELLED |
| 在服务器返回状态之前截止时间过期 | GRPC_STATUS_DEADLINE_EXCEEDED |
| 服务器上找不到方法 | GRPC_STATUS_UNIMPLEMENTED |
| 服务器正在关闭 | GRPC_STATUS_UNAVAILABLE |
| 服务器抛出异常(或执行了除返回状态码之外的操作来终止 RPC) | GRPC_STATUS_UNKNOWN |
网络故障
| 情况 | 状态码 |
|---|---|
| 截止时间过期前未传输数据。也适用于传输了一些数据,且在截止时间过期前未检测到其他故障的情况 | GRPC_STATUS_DEADLINE_EXCEEDED |
| 在连接断开之前传输了一些数据(例如,请求元数据已写入 TCP 连接) | GRPC_STATUS_UNAVAILABLE |
协议错误
| 情况 | 状态码 |
|---|---|
| 无法解压缩,但支持相应的压缩算法 | GRPC_STATUS_INTERNAL |
| 服务器不支持客户端使用的压缩机制 | GRPC_STATUS_UNIMPLEMENTED |
| 达到流量控制资源限制 | GRPC_STATUS_RESOURCE_EXHAUSTED |
| 违反流量控制协议 | GRPC_STATUS_INTERNAL |
| 解析返回的状态时出错 | GRPC_STATUS_UNKNOWN |
| 未经身份验证:凭据未能获取元数据 | GRPC_STATUS_UNAUTHENTICATED |
| 权限元数据中设置了无效的主机 | GRPC_STATUS_UNAUTHENTICATED |
| 解析响应 Protocol Buffer 时出错 | GRPC_STATUS_INTERNAL |
| 解析请求 Protocol Buffer 时出错 | GRPC_STATUS_INTERNAL |
语言支持
提供了多种语言的示例代码,展示了如何处理标准错误以及更丰富的错误详细信息。
| 语言 | 示例 |
|---|---|
| C++ | C++ 错误处理示例 |
| C++ 错误详细信息示例 | |
| Go | Go 错误处理示例 |
| Go 错误详细信息示例 | |
| Java | Java 错误处理示例 |
| Java 错误详细信息示例 | |
| Node | Node 错误处理示例 |
| Python | Python 错误详细信息示例 |
grpc-errors 仓库也包含额外的错误处理示例。