【问题标题】:Using Polly to retry after HttpStatusCode.Unauthorized在 HttpStatusCode.Unauthorized 之后使用 Polly 重试
【发布时间】:2017-01-28 13:00:38
【问题描述】:

我正在调用外部 API,并且想要处理调用返回 UnauthorizedHttpResponseMessage 的事件。发生这种情况时,我想刷新访问令牌并再次拨打电话。

我正在尝试将Polly 与以下代码一起使用:

    public async Task<HttpResponseMessage> MakeGetRequestAsync()
    {
        var retryPolicy = Policy
            .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized)
            .Retry(1, (exception, retryCount) =>
            {
                RefreshAccessToken();
            });

        var result = await retryPolicy.ExecuteAsync(() => CallApiAsync());

        return result;
    }


    private async Task<HttpResponseMessage> CallApiAsync()
    {
        var url = Options.ResourceSandboxUrl;

        var httpClient = new HttpClient();
        SetRequestHeaders(httpClient);
        var response = await httpClient.GetAsync(url);

        response.StatusCode = HttpStatusCode.Unauthorized;
        return response;
    }

我在ExecuteAsync 语句和DoSomethingAsync 中设置断点 - 当我越过ExecuteAsync 时,DoSomethingAsync 未被调用,控制权返回给调用MakeGetRequestAsync 的函数

我不明白为什么不调用 DoSomethingAsync - 任何人都可以帮助我实现我想要实现的目标吗?

我查看了有关 Stack Overflow 的 Polly 文档和 Polly 问题,但我不知道发生了什么......

【问题讨论】:

    标签: c# asp.net-mvc polly


    【解决方案1】:

    要使用ExecuteAsync(),您必须将策略声明为.RetryAsync(...),而不是.Retry(...)

    如果您的实际代码与上面的代码示例完全一致,.ExecuteAsync(...) 将抛出 .Retry(...) [同步策略] 和 .ExecuteAsync(...) [异步执行] 之间的不匹配。由于抛出了这个异常,CallApiAsync() 确实从未被调用过。调用MakeGetRequestAsync()时应该可以看到抛出的异常@

    整体代码方法看起来不错:这个重试刷新身份验证是proven pattern with Polly

    【讨论】:

    • 我正在使用相同的重试模式并获得异常“请在调用异步 ExecuteAsync(和类似)方法时使用异步定义的策略。”。我正在努力理解出了什么问题……而你救了我。谢谢..!!
    【解决方案2】:

    我回复这个老问题只是为了指出官方记录了这种模式的 Polly wiki 页面:

    retry-to-refresh-authorization

    特别是sn-p建议的代码:

    var authorisationEnsuringPolicy = Policy
        .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized) 
        .RetryAsync(
           retryCount: 1, // Consider how many retries. If auth lapses and you have valid credentials, one should be enough; too many tries can cause some auth systems to blacklist. 
           onRetryAsync: async (outcome, retryNumber, context) => FooRefreshAuthorizationAsync(context), 
          /* more configuration */); 
    
    var response = authorisationEnsuringPolicy.ExecuteAsync(context => DoSomethingThatRequiresAuthorization(context), cancellationToken);
    

    FooRefreshAuthorizationAsync(...) 方法可以获取一个新的授权令牌,并使用Polly.Context 将其传递给通过策略执行的委托。

    【讨论】:

      【解决方案3】:

      这就是 .net 中 async await 的工作方式,当你的代码执行到 await 时,会发生两件事

      1. 您的代码的当前线程应该释放以使您的代码异步,这意味着您的方法应该返回

      2. 当您等待的任务完成时,您的方法应该从原来的位置继续

      【讨论】:

      • 谢谢,我该如何编写这段代码来做我想做的事?
      • 关于异步执行的所有这些都是正确的,但这些都与用户对 CallApiAsync() 的调用不是通过 Polly 进行的原因无关。
      猜你喜欢
      • 2022-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多