Polly + API 结果 Return 错误的服务
Polly + API Services That Return Errors as Results
我正在使用一个网络 API,如果查询不存在的数据,它将 return 代码为 404,如果数据格式不正确或存在其他问题,则会出现其他错误。然后导致 HttpRequestException。
现在我在考虑一个细节。我在该 HttpClient 连接上使用 Polly 以确保它在出现通信问题时重试。
在这种情况下,它是否会按预期工作,或者 Polly 会在服务器抛出“未找到”或“错误请求”等错误的情况下继续重试?
我是这样配置的
services.AddHttpClient<OntraportHttpClient>()
.AddTransientHttpErrorPolicy(p =>
p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(600)));
你有点误会了,400 Bad Request 或 404 Not Found 不会导致 HttpRequestException
.
除非您明确调用 EnsureSuccessStatusCode。
AddTransientHttpErrorPolicy 将检查以下内容:
- 408 超时
- 5xx 服务器错误
- HttpRequestException
因此,您看不到 400、404 或 429 太多请求(back-pressure 情况下的典型响应代码)都不会导致您的 Polly 策略被触发。除非您显式调用 EnsureSuccessStatusCode
方法。
更新:添加删除用例
用例
假设我们有一个 REST 服务,它公开了给定资源的删除功能(由特定 URL 和通过 DELETE HTTP 动词解决)。
从消耗的角度来看,此删除可能会处于 3 种不同状态之一:
- 成功
- 已经完成
- 失败
您可以在互联网上找到几个参数,这是成功的正确状态。如果它是异步的,它可以是 body 的 200(OK)或没有 body 的 204(无内容)或 202(已接受)。有时也使用 404(未找到)。
当您尝试删除已删除的项目时,可能会出现已完成状态。如果没有软删除,很难判断给定的资源以前是否存在过或者它从未成为您系统的一部分。如果您有软删除,则该服务可能 return 404 用于已删除的资源和 400(错误请求)用于未知资源。
只要在请求处理过程中出现故障,就可以将其视为临时或永久故障。如果存在网络问题,那么它可以被视为 temporary/transient 问题(这可以表现为 HttpRequestException
)。如果存在数据库中断并且服务能够检测到它,那么它可以快速失败并 return 返回 5XX 响应,或者它可以尝试进行故障转移。如果有太多未决请求,则服务可能会考虑限制它们并使用 back-pressure 来减轻负载。它可能 return 带有 429(太多请求)以及适当的 Retry-After
header.
永久性错误,例如服务已永久关闭或主动拒绝 TLS 1.3 下的网络连接尝试,需要人工干预才能修复。
幂等性
每当我们谈论重试模式时,我们需要考虑以下几点:
- 潜在引入的可观察影响是可以接受的
- 可以重做操作,没有任何不可逆的副作用
- 与承诺的可靠性相比,引入的复杂性可以忽略不计
第二个标准通常称为幂等性。它说,如果您使用相同的输入多次调用方法/端点,那么它应该 return 相同的输出而没有任何副作用。
如果您的服务的删除功能可以被认为是幂等的,那么就没有已经完成这样的状态。如果你调用它 100 次,那么它应该总是 return 并带有“yepp,那已经消失了”。因此,考虑到这一点,在幂等删除的情况下,使用 204 或 404 return 可能是有意义的。
弹性策略
每当我们谈论战略时,对我来说都意味着一系列有弹性的政策。如果以前的政策无法“解决”问题,那么后者会尝试这样做(因此存在政策升级)。
Server-side:您可以使用 Bulk-head 策略来控制最大并发调用数,但如果超过阈值,则可以开始限制请求。
Client-side:您可以为每个单独的请求设置超时,并且可以在 temporary/transient 失败的情况下应用重试策略。您还可以为所有重试尝试定义全局超时。或者,如果服务被视为不堪重负或发生故障,您可以应用断路器来监视连续故障和 back-off 给定时间段。
我的 2 美分是在 client-side 上应用单一的弹性策略可能不足以拥有一个强大而有弹性的系统。可能需要多个策略(双方)来为有问题的时期建立通信协议。
我正在使用一个网络 API,如果查询不存在的数据,它将 return 代码为 404,如果数据格式不正确或存在其他问题,则会出现其他错误。然后导致 HttpRequestException。
现在我在考虑一个细节。我在该 HttpClient 连接上使用 Polly 以确保它在出现通信问题时重试。
在这种情况下,它是否会按预期工作,或者 Polly 会在服务器抛出“未找到”或“错误请求”等错误的情况下继续重试?
我是这样配置的
services.AddHttpClient<OntraportHttpClient>()
.AddTransientHttpErrorPolicy(p =>
p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(600)));
你有点误会了,400 Bad Request 或 404 Not Found 不会导致 HttpRequestException
.
除非您明确调用 EnsureSuccessStatusCode。
AddTransientHttpErrorPolicy 将检查以下内容:
- 408 超时
- 5xx 服务器错误
- HttpRequestException
因此,您看不到 400、404 或 429 太多请求(back-pressure 情况下的典型响应代码)都不会导致您的 Polly 策略被触发。除非您显式调用 EnsureSuccessStatusCode
方法。
更新:添加删除用例
用例
假设我们有一个 REST 服务,它公开了给定资源的删除功能(由特定 URL 和通过 DELETE HTTP 动词解决)。
从消耗的角度来看,此删除可能会处于 3 种不同状态之一:
- 成功
- 已经完成
- 失败
您可以在互联网上找到几个参数,这是成功的正确状态。如果它是异步的,它可以是 body 的 200(OK)或没有 body 的 204(无内容)或 202(已接受)。有时也使用 404(未找到)。
当您尝试删除已删除的项目时,可能会出现已完成状态。如果没有软删除,很难判断给定的资源以前是否存在过或者它从未成为您系统的一部分。如果您有软删除,则该服务可能 return 404 用于已删除的资源和 400(错误请求)用于未知资源。
只要在请求处理过程中出现故障,就可以将其视为临时或永久故障。如果存在网络问题,那么它可以被视为 temporary/transient 问题(这可以表现为 HttpRequestException
)。如果存在数据库中断并且服务能够检测到它,那么它可以快速失败并 return 返回 5XX 响应,或者它可以尝试进行故障转移。如果有太多未决请求,则服务可能会考虑限制它们并使用 back-pressure 来减轻负载。它可能 return 带有 429(太多请求)以及适当的 Retry-After
header.
永久性错误,例如服务已永久关闭或主动拒绝 TLS 1.3 下的网络连接尝试,需要人工干预才能修复。
幂等性
每当我们谈论重试模式时,我们需要考虑以下几点:
- 潜在引入的可观察影响是可以接受的
- 可以重做操作,没有任何不可逆的副作用
- 与承诺的可靠性相比,引入的复杂性可以忽略不计
第二个标准通常称为幂等性。它说,如果您使用相同的输入多次调用方法/端点,那么它应该 return 相同的输出而没有任何副作用。
如果您的服务的删除功能可以被认为是幂等的,那么就没有已经完成这样的状态。如果你调用它 100 次,那么它应该总是 return 并带有“yepp,那已经消失了”。因此,考虑到这一点,在幂等删除的情况下,使用 204 或 404 return 可能是有意义的。
弹性策略
每当我们谈论战略时,对我来说都意味着一系列有弹性的政策。如果以前的政策无法“解决”问题,那么后者会尝试这样做(因此存在政策升级)。
Server-side:您可以使用 Bulk-head 策略来控制最大并发调用数,但如果超过阈值,则可以开始限制请求。
Client-side:您可以为每个单独的请求设置超时,并且可以在 temporary/transient 失败的情况下应用重试策略。您还可以为所有重试尝试定义全局超时。或者,如果服务被视为不堪重负或发生故障,您可以应用断路器来监视连续故障和 back-off 给定时间段。
我的 2 美分是在 client-side 上应用单一的弹性策略可能不足以拥有一个强大而有弹性的系统。可能需要多个策略(双方)来为有问题的时期建立通信协议。