This is the multi-page printable view of this section. Click here to print.
重试和退避弹性策略
- 1: 重试弹性策略
- 2: 覆盖默认重试弹性策略
1 - 重试弹性策略
请求可能因瞬时错误而失败,例如遇到网络拥塞、重新路由到过载实例等。有时,请求也可能因已设置的其他弹性策略而失败,例如触发了定义的超时或熔断器策略。
在这些情况下,配置 retries 可以:
- 将相同请求发送到不同的实例,或
- 在条件清除后重试发送请求。
重试和超时协同工作,超时确保您的系统在需要时快速失败,而重试从临时故障中恢复。
Dapr 提供默认弹性策略,您可以使用用户定义的重试策略覆盖它们。
重要
每个发布订阅组件都有自己的内置重试行为。显式应用 Dapr 弹性策略不会覆盖这些隐式重试策略。相反,弹性策略会增强内置重试,这可能导致消息重复聚集。重试策略格式
示例 1
spec:
policies:
# Retries are named templates for retry configurations and are instantiated for life of the operation.
retries:
pubsubRetry:
policy: constant
duration: 5s
maxRetries: 10
retryForever:
policy: exponential
maxInterval: 15s
maxRetries: -1 # Retry indefinitely
示例 2
spec:
policies:
retries:
retry5xxOnly:
policy: constant
duration: 5s
maxRetries: 3
matching:
httpStatusCodes: "429,500-599" # retry the HTTP status codes in this range. All others are not retried.
gRPCStatusCodes: "1-4,8-11,13,14" # retry gRPC status codes in these ranges and separate single codes.
规范元数据
以下重试选项是可配置的:
| 重试选项 | 描述 |
|---|---|
policy | 确定退避和重试间隔策略。有效值为 constant 和 exponential。默认为 constant。 |
duration | 确定重试之间的时间间隔。仅适用于 constant 策略。有效值为 200ms、15s、2m 等格式。默认为 5s。 |
maxInterval | 确定exponential 退避策略可以增长到的重试之间的最大间隔。额外的重试总是在 maxInterval 的持续时间后发生。默认为 60s。有效值为 5s、1m、1m30s 等格式。 |
maxRetries | 要尝试的最大重试次数。-1 表示无限次重试,而 0 表示不会重试请求(本质上表现为未设置重试策略)。默认为 -1。 |
matching.httpStatusCodes | 可选:逗号分隔的要重试的 HTTP 状态码或状态码范围字符串。未列出的状态码不会被重试。 有效值:100-599,参考 格式: <code> 或范围 <start>-<end>示例:“429,501-503” 默认:空字符串 "" 或未设置字段。重试所有 HTTP 错误。 |
matching.gRPCStatusCodes | 可选:逗号分隔的要重试的 gRPC 状态码或状态码范围字符串。未列出的状态码不会被重试。 有效值:0-16,参考 格式: <code> 或范围 <start>-<end>示例:“4,8,14” 默认:空字符串 "" 或未设置字段。重试所有 gRPC 错误。 |
指数退避策略
指数退避窗口使用以下公式:
BackOffDuration = PreviousBackOffDuration * (Random value from 0.5 to 1.5) * 1.5
if BackOffDuration > maxInterval {
BackoffDuration = maxInterval
}
重试状态码
当应用程序跨越多个服务时,特别是在像 Kubernetes 这样的动态环境中,服务可能因各种原因而消失,网络调用可能会开始挂起。状态码提供了对我们操作的洞察以及它们在生产中可能失败的位置。
HTTP
下表包含您可能收到的一些 HTTP 状态码示例,以及您是否应该或不应该重试某些操作。
| HTTP 状态码 | 建议重试? | 描述 |
|---|---|---|
| 404 Not Found | ❌ 否 | 资源不存在。 |
| 400 Bad Request | ❌ 否 | 您的请求无效。 |
| 401 Unauthorized | ❌ 否 | 尝试获取新凭据。 |
| 408 Request Timeout | ✅ 是 | 服务器等待请求超时。 |
| 429 Too Many Requests | ✅ 是 | (如果存在,请遵守 Retry-After 头)。 |
| 500 Internal Server Error | ✅ 是 | 服务器遇到意外情况。 |
| 502 Bad Gateway | ✅ 是 | 网关或代理接收到无效响应。 |
| 503 Service Unavailable | ✅ 是 | 服务可能会恢复。 |
| 504 Gateway Timeout | ✅ 是 | 临时网络问题。 |
gRPC
下表包含您可能收到的一些 gRPC 状态码示例,以及您是否应该或不应该重试某些操作。
| gRPC 状态码 | 建议重试? | 描述 |
|---|---|---|
| Code 1 CANCELLED | ❌ 否 | N/A |
| Code 3 INVALID_ARGUMENT | ❌ 否 | N/A |
| Code 4 DEADLINE_EXCEEDED | ✅ 是 | 使用退避重试 |
| Code 5 NOT_FOUND | ❌ 否 | N/A |
| Code 8 RESOURCE_EXHAUSTED | ✅ 是 | 使用退避重试 |
| Code 14 UNAVAILABLE | ✅ 是 | 使用退避重试 |
基于状态码的重试过滤器
重试过滤器允许通过指定应应用重试的 HTTP 和 gRPC 状态码或范围,对重试策略进行细粒度控制。
spec:
policies:
retries:
retry5xxOnly:
# ...
matching:
httpStatusCodes: "429,500-599" # retry the HTTP status codes in this range. All others are not retried.
gRPCStatusCodes: "4,8-11,13,14" # retry gRPC status codes in these ranges and separate single codes.
注意
状态码的字段值必须遵循上述指定的格式。格式错误的值会产生错误日志(“Could not read resiliency policy”),并且daprd 启动序列将继续。演示
观看 Diagrid 的 Dapr v1.15 庆祝活动期间演示的演示,了解如何使用 Diagrid Conductor 设置重试状态码过滤器。
后续步骤
相关链接
尝试其中一个弹性快速入门:
2 - 覆盖默认重试弹性策略
Dapr 为任何不成功的请求(如故障和临时错误)提供默认重试。在弹性规范中,您可以通过使用保留的命名关键字定义策略来覆盖 Dapr 的默认重试逻辑。例如,定义一个名为 DaprBuiltInServiceRetries 的策略可以覆盖通过服务间请求在边车之间发生故障时的默认重试。策略覆盖不会应用于特定目标。
注意:虽然您可以使用更稳健的重试来覆盖默认值,但不能使用低于提供的默认值的值进行覆盖,也不能完全移除默认重试。这可以防止意外的停机。
下表描述了 Dapr 的默认重试以及用于覆盖它们的策略关键字:
| 功能 | 覆盖关键字 | 默认重试行为 | 描述 |
|---|---|---|---|
| 服务调用 | DaprBuiltInServiceRetries | 每次调用重试的退避间隔为 1 秒,最多重试 3 次。 | 边车对边车的请求(服务调用方法调用)失败并导致 gRPC 代码 Unavailable 或 Unauthenticated |
| Actors | DaprBuiltInActorRetries | 每次调用重试的退避间隔为 1 秒,最多重试 3 次。 | 边车对边车的请求(Actor 方法调用)失败并导致 gRPC 代码 Unavailable 或 Unauthenticated |
| Actor 提醒 | DaprBuiltInActorReminderRetries | 每次调用重试采用指数退避,初始间隔为 500ms,最大间隔为 60s,持续时间为 15 分钟 | 向状态存储持久化 Actor 提醒失败的请求 |
| 初始化重试 | DaprBuiltInInitializationRetries | 每次调用执行 3 次重试,采用指数退避,初始间隔为 500ms,持续时间为 10 秒 | 向应用程序发出请求以检索给定规范时的故障。例如,检索订阅、组件或弹性规范失败 |
下面的弹性规范示例展示了如何使用保留的命名关键字 ‘DaprBuiltInServiceRetries’ 来覆盖_所有_服务调用请求的默认重试。
同时还定义了一个名为 ‘retryForever’ 的重试策略,该策略仅应用于 appB 目标。appB 使用 ‘retryForever’ 重试策略,而所有其他应用程序服务调用重试故障则使用被覆盖的 ‘DaprBuiltInServiceRetries’ 默认策略。
spec:
policies:
retries:
DaprBuiltInServiceRetries: # 覆盖服务间调用的默认重试行为
policy: constant
duration: 5s
maxRetries: 10
retryForever: # 用户定义的重试策略会替换默认重试。目标仅依赖于应用的策略。
policy: exponential
maxInterval: 15s
maxRetries: -1 # 无限期重试
targets:
apps:
appB: # 目标服务的 app-id
retry: retryForever
相关链接
尝试其中一个弹性快速入门: