将错误返回为结果的Polly + API服务 用例幂等弹性策略

问题描述

我正在使用一个Web API,如果查询不存在的数据,它将返回代码404,如果数据存在其他问题,则返回错误,否则将返回其他错误。然后会导致HttpRequestException。

现在我正在考虑一个细节。我在该HttpClient连接上使用Polly以确保在发生通信问题时重试。

在这种情况下,它会按预期运行,还是在出现服务器引发的错误(例如“未找到”或“错误请求”)的情况下,波莉会继续重试?

我正在这样配置

services.AddHttpClient<OntraportHttpClient>()
    .AddTransientHttpErrorPolicy(p =>
        p.WaitAndRetryAsync(3,_ => TimeSpan.FromMilliseconds(600)));

解决方法

您有点误解,“ 400错误请求”或“ 404未找到”不会导致HttpRequestException

除非您明确致电EnsureSuccessStatusCode

AddTransientHttpErrorPolicy将检查以下内容:

  • 408超时
  • 5xx服务器错误
  • HttpRequestException

因此,您将不会看到400、404或429太多请求(在背压的情况下,典型响应代码)将不会触发您的Polly策略。除非您显式调用EnsureSuccessStatusCode方法。


更新:添加DELETE用例

用例

让我们假设有一个REST服务,该服务公开给定资源的删除功能(通过特定的URL并通过DELETE HTTP动词寻址)。

从消耗的角度来看,这种清除可能会以3种不同的状态之一结束:

  • 成功
  • 已经完成
  • 失败

您可以在互联网上找到几个成功的正确参数。如果它是异步的,则可以是200(确定)(带主体)或204(无内容)(不带主体)或202(已接受)。有时也使用404(未找到)。

当您尝试删除已删除的项目时,可能会出现已完成状态。如果不进行软删除,则很难说出给定的资源曾经存在过,或者从未成为系统的一部分。如果您进行了软删除,则该服务可以为已删除的资源返回404,为未知资源返回400(错误请求)。

每当在请求处理过程中发生故障时,都可以将其视为暂时性或永久性故障。如果存在网络问题,则可以将其视为暂时/暂时性问题(可以显示为HttpRequestException)。如果数据库中断并且服务能够检测到它,则它可以快速故障并返回5XX响应,或者可以尝试故障转移。如果有太多待处理的请求,则服务可能会考虑限制它们并使用背压来减轻负载。它可能会返回429(请求过多)以及相应的Retry-After标头。

永久性错误(例如服务已被永久关闭或在TLS 1.3下主动拒绝网络连接尝试)需要人工干预才能解决。

幂等

每当我们谈论重试模式时,我们都需要考虑以下几点:

  • 可能引入的可观察的影响是可以接受的
  • 可以重做该操作,而没有任何不可逆的副作用
  • 与承诺的可靠性相比,引入的复杂性可以忽略不计

第二个标准通常称为幂等。它说,如果您使用相同的输入多次调用方法/端点,那么它应该返回相同的输出而没有任何副作用。

如果可以将您服务的删除功能视为幂等,则没有“已完成”这样的状态。如果您叫它100次,那么它应该总是返回“是的,没了”。因此,请记住,在幂等删除的情况下,返回204或404可能很有意义。

弹性策略

每当我们谈论战略时,对我来说,这意味着一系列弹性的政策。如果前者的政策无法“解决”问题,则后者会尝试解决该问题(因此会升级政策)。

服务器端:您可以使用批量策略来控制并发呼叫的最大数量,但是如果已超过阈值,则可以开始限制请求。

客户端:对于每个单独的请求,您都可以超时,并且可以在临时/暂时失败的情况下应用重试策略。您还可以为所有重试尝试定义全局超时。或者,如果服务被视为不堪重负或发生故障,则可以应用断路器来监视连续的故障并在给定的时间后退。

我的2美分只是在客户端应用单个弹性策略,可能不足以拥有一个健壮和弹性的系统。可能需要采取一些策略(双方)才能在出现问题期间建立通信协议。