【问题标题】:Polly timeout policy clarificationPolly 超时政策说明
【发布时间】:2017-09-11 00:41:26
【问题描述】:

我正在尝试让超时策略正常工作。 我在集成 api 时有以下要求。

  1. 创建一个 http 请求以调用端点 1 并传递 transactionID 并捕获结果
  2. 如果 http 请求在 20 秒内没有响应,则发送具有相同事务 ID 的取消请求并捕获结果

对于这个任务,我想使用 Polly,在我看来,它是一个很棒的组件,可以帮助处理瞬态故障。但是,由于我对这项技术非常陌生,我只想确定我是否正确实施。

首先,我已经像这样使用 Polly 创建了超时策略

var timeoutPolicy =
    Policy.TimeoutAsync(
        TimeSpan.FromSeconds( 20 ),
        TimeoutStrategy.Optimistic,
        async ( context, timespan, task ) => {
            //write here the cancel request 
        } );

然后我就可以执行策略了

var policyResult = await timeoutPolicy.ExecuteAndCaptureAsync( async () => {
    //make here the request 1
} );

我从文档中得到的是,如果在 timeoutPolicy.ExecuteAndCaptureAsync 委托中发生超时,Polly 会自动调用 onTimeout 委托。对吧?

但是我的问题是:

  • 如果在执行委托中发生异常会怎样?我应该把那个 polly 结构包装在一个 try catch 中吗?
  • 当我分析策略结果时,如何了解是否发生超时?

【问题讨论】:

    标签: c# polly transient-failure


    【解决方案1】:

    我从文档中得到的是,如果在 ExecuteAndCaptureAsync 委托 Polly 自动调用 onTimeout 委托。对吧?

    Correct.

    如果在执行委托中发生异常会发生什么?

    因为您使用的是 ExecuteAndCaptureAsync(...),所以例外是 placed in policyResult.FinalException

    我应该将那个 polly 结构包装在 try catch 中吗?

    因为你使用的是ExecuteAndCaptureAsync(..),所以异常放在policyResult.FinalException中,所以你不需要try-catch。

    当我分析策略结果时,我如何了解是否发生了超时?

    TimeoutPolicy throws TimeoutRejectedException 超时。因为您使用的是 ExecuteAndCaptureAsync(...),您应该会发现该异常位于 policyResult.FinalException 中。


    还有几个cmets。使用TimeoutStrategy.Optimisitic,即based on co-operative cancellation by CancellationToken,您应该执行一个带取消令牌的委托:

    var policyResult = await timeoutPolicy.ExecuteAndCaptureAsync(async (ct) => {
        //make request 1, in a form which responds to the cancellation token ct
    }, userCancellationToken /* CancellationToken.None is acceptable. Polly will merge its timing-out CancellationToken into ct, during policy execution. */
    );
    

    其次,作为在onRetryAsync: async ( context, timespan, task ) => { ... } 中调用取消请求的替代方法,您可以选择使用如下模式使代码更具顺序性/嵌套更少:

    var policyResult = await timeoutPolicy.ExecuteAndCaptureAsync(async (ct) => {
        //make request 1, in a form which responds to the cancellation token ct
    }, CancellationToken.None);
    
    if (policyResult.Outcome == OutcomeType.Failure && policyResult.FinalException is TimeoutRejectedException)
    {
        //write here the cancel request 
    }
    

    更新:调用取消请求可以以任何方式工作 - 从onRetryAsync 内部,或按顺序,如上所示。顺序版本的一个优点是,如果 cancel 请求 因异常而失败,它可以更容易地推断会发生什么。使用嵌套方法(在 onRetryAsync 中调用取消请求),最终捕获到 policyResult.FinalException 中的异常可能来自初始请求或取消请求 - 可能很难分辨是哪一个。

    【讨论】:

    • 您好,非常感谢您非常明确的回答。另外我想了解如何检索我的 http 请求调用的结果并将其返回。文档说在 policyResult 变量中我应该使用 Result 成员,但这对我不可用。
    • PolicyResult.Result 在使用泛型方法重载.ExecuteAndCaptureAsync<TResult>(...) 时可用; TResult 是您正在执行的函数的返回类型。如果函数返回TResult,编译器应该为您选择正确的.ExecuteAndCaptureAsync<TResult>(...) 重载。如果不是,请尝试通过为您的TResult 明确声明.ExecuteAndCaptureAsync<TResult>(...) 来强制它。此处的规范github.com/App-vNext/Polly/blob/… 显示它可以正常工作,包括。编译器重载推理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 2022-07-10
    • 2019-08-22
    • 1970-01-01
    • 2016-10-13
    • 2015-02-18
    • 2020-10-29
    相关资源
    最近更新 更多