重试

gRPC 让处理故障不再烦恼!通过 OpenCensus 和 OpenTelemetry 支持,获得细粒度的重试控制和详细的洞察。

重试

gRPC 让处理故障不再烦恼!通过 OpenCensus 和 OpenTelemetry 支持,获得细粒度的重试控制和详细的洞察。

概述

重试是提高服务可靠性的关键模式。通过重新尝试失败的操作,应用程序可以克服临时的网络或服务器故障等问题。这对于现代云应用程序处理不可避免的瞬时故障至关重要。

最佳实践是,应用程序应了解哪些失败操作适合重试,定义重试延迟的指数退避参数,确定重试尝试次数,并监控重试指标。

gRPC 客户端重试的工作原理

gRPC 的内置重试逻辑会保存调用历史以备潜在的重试,并监控 RPC 事件。即使未配置重试策略,gRPC 仍会保存调用历史,以防需要执行透明重试(将在后续部分讨论)。请注意,“重试”是指将失败的调用替换为新调用,并在新创建的调用上重放调用历史。

如果满足特定条件——RPC 以与重试策略中可重试状态码匹配的失败状态码关闭,并且未超出重试尝试限制——gRPC 将在指数退避延迟后创建新的重试流。

gRPC 还支持重试节流和服务端回压等其他功能。有关更多详细信息,请参阅客户端重试的 gRFC

一旦收到响应头,RPC 就被提交。将不再尝试进一步的重试,gRPC 会将 RPC 交给应用程序处理。

下图显示了 gRPC 重试内部的架构概述。

sequenceDiagram
  Application ->> gRPC Client: Configure retry policy. <br> Send request to dns:///my-service
  gRPC Client ->> gRPC Client: Save message
  gRPC Client ->> Server: Create initial attempt
  Server -->> gRPC Client : RPC closed with error 
  gRPC Client ->> Server: Create retry attempt 1 
  Server -->> gRPC Client: Successful 
  gRPC Client ->> Application: No more retry. Proceed.

重试配置

重试默认启用,但没有默认的重试策略。在大多数情况下,如果没有重试策略,gRPC 无法安全地重试 RPC。只有因低级竞争条件失败的 RPC 才会被重试,并且仅限于 gRPC 确定 RPC 未经服务器处理过的情况。这被称为“透明重试”。您可以配置重试策略,允许 gRPC 在更多情况下更积极地重试 RPC。在创建通道时,您也可以完全禁用重试,这将禁用透明重试和任何已配置的重试策略。

您可以通过关注 gRPC 支持的关键步骤和配置来优化应用程序的重试功能。

  • 最大重试尝试次数
  • 指数退避
  • 可重试状态码集合

重试可通过gRPC 服务配置进行配置,粒度为每个方法。配置包含以下参数

"retryPolicy": {
  "maxAttempts": 4,
  "initialBackoff": "0.1s",
  "maxBackoff": "1s",
  "backoffMultiplier": 2,
  "retryableStatusCodes": [
    "UNAVAILABLE"
  ]
}

退避延迟会应用正负 20% 的抖动(jitter),以避免大量客户端同时冲击服务器。在上面的示例配置中,initialBackoff 设置为 100ms,因此第一次尝试后的实际退避延迟将在 [80ms, 120ms] 范围内的随机时间段。

gRPC 支持节流限制,以防止由于重试导致的服务器过载。以下是重试节流配置的示例

"retryThrottling": {
  "maxTokens": 10,
  "tokenRatio": 0.1
}

对于每个服务器,gRPC 客户端跟踪一个 token_count(初始设置为 maxTokens)。失败的 RPC 使计数减 1,成功的 RPC 使计数增加 tokenRatio。如果 token_count 降至 maxTokens 的一半以下,重试将暂停,直到计数恢复。

此外,对冲是重试的一个补充功能,也可以类似地配置。有关更多详细信息,请参阅对冲指南

重试可观测性

启用重试功能后,gRPC 支持暴露 OpenCensus 和 OpenTelemetry 指标。以下是可用的 OpenTelemetry 重试尝试统计信息示例

  • grpc.client.attempt.started
  • grpc.client.attempt.duration
  • grpc.client.attempt.sent_total_compressed_message_size
  • grpc.client.attempt.rcvd_total_compressed_message_size

按调用级别划分的指标

  • grpc.client.call.duration

以及服务器端指标

  • grpc.server.call.started
  • grpc.server.call.sent_total_compressed_message_size
  • grpc.server.call.rcvd_total_compressed_message_size
  • grpc.server.call.duration

有关深入的指标和跟踪信息以及配置说明,请参见Otel 指标的 gRFC重试状态的 gRFC

语言指南和示例

语言示例文档
C++
GoGo 示例
JavaJava 示例Java 文档
PythonPython 示例

附加资源

最后修改时间 2024 年 10 月 10 日:更新重试指南图示 (#1371) (f13bf5b)