重试
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
的一半以下,重试将暂停,直到计数恢复。
此外,对冲是重试的一个补充功能,也可以类似地配置。有关更多详细信息,请参阅对冲指南。
重试可观测性
启用重试功能后,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++ | ||
Go | Go 示例 | |
Java | Java 示例 | Java 文档 |
Python | Python 示例 |