重试
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 也可能会执行透明重试。这些重试的程度取决于失败发生的时间。
- 当 RPC 从未离开客户端时,gRPC 可能会执行无限次透明重试。
- 当 RPC 到达 gRPC 服务器库,但从未被服务器应用逻辑处理时,gRPC 会执行一次透明重试。请注意这种类型的重试,因为它会增加网络负载。
您可以通过关注 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
的一半以下,重试将暂停,直到计数恢复。
此外,对冲(hedging)是重试的补充功能,也可以类似地进行配置。有关更多详细信息,请参阅对冲指南。
重试可观测性
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
有关深入的指标和跟踪信息以及配置说明,请参阅gRFC Otel 指标、gRFC 重试状态。
语言指南和示例
语言 | 示例 | 文档 |
---|---|---|
C++ | ||
Go | Go 示例 | |
Java | Java 示例 | Java 文档 |
Python | Python 示例 |