错误处理

gRPC 如何处理错误以及 gRPC 错误代码。

错误处理

gRPC 如何处理错误以及 gRPC 错误代码。

标准错误模型

正如您在我们的概念文档和示例中所看到的,当 gRPC 调用成功完成时,服务器会向客户端返回一个 OK 状态(根据语言的不同,OK 状态可能不会直接在您的代码中使用)。但是如果调用不成功会发生什么呢?

如果发生错误,gRPC 会返回其错误状态代码之一,以及一个可选的字符串错误消息,其中提供了有关发生情况的更多详细信息。所有支持的语言的 gRPC 客户端都可以使用错误信息。

更丰富的错误模型

上面描述的错误模型是官方的 gRPC 错误模型,所有 gRPC 客户端/服务器库都支持它,并且它与 gRPC 数据格式(无论是协议缓冲区还是其他格式)无关。您可能已经注意到它非常有限,不包括传递错误详细信息的功能。

但是,如果您使用协议缓冲区作为数据格式,您可能希望考虑使用 Google 开发和使用的更丰富的错误模型,如此处所述。此模型使服务器能够返回,客户端能够使用表示为一个或多个 protobuf 消息的其他错误详细信息。它进一步指定了一个标准错误消息类型集,以涵盖最常见的需求(例如无效参数、配额违规和堆栈跟踪)。此额外错误信息的 protobuf 二进制编码作为响应中的尾部元数据提供。

C++、Go、Java、Python 和 Ruby 库已经支持这种更丰富的错误模型,并且至少 grpc-web 和 Node.js 库有开放问题要求它。如果需要,其他语言库可能会在将来添加支持,因此如果有兴趣,请检查它们的 github 存储库。但是请注意,用 C 编写的 grpc-core 库不太可能支持它,因为它是有意与数据格式无关的。

如果您不使用协议缓冲区,您可以使用类似的方法(将错误详细信息放在尾部响应元数据中),但您可能需要查找或开发库支持来访问此数据,以便在您的 API 中实际使用它。

但是,在决定是否使用这种扩展的错误模型时,需要注意一些重要的考虑因素,包括

  • 在错误详细信息有效负载的要求和期望方面,扩展错误模型的库实现可能在不同语言之间不一致
  • 现有的代理、记录器和其他标准 HTTP 请求处理器无法查看错误详细信息,因此无法将其用于监视或其他目的
  • 尾部中的其他错误详细信息会干扰队首阻塞,并且由于更频繁的缓存未命中,会降低 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
解析响应协议缓冲区时出错GRPC_STATUS_INTERNAL
解析请求协议缓冲区时出错GRPC_STATUS_INTERNAL

语言支持

多种语言提供了关于如何处理标准错误以及更丰富的错误详细信息的示例代码。

语言示例
C++C++ 错误处理示例
C++ 错误详细信息示例
GoGo 错误处理示例
Go 错误详细信息示例
JavaJava 错误处理示例
Java 错误详细信息示例
NodeNode 错误处理示例
PythonPython 错误详细信息示例

grpc-errors 仓库也包含其他错误处理示例。

上次修改时间:2024年2月29日:状态码用户指南 (#1263) (fb661d4)