标签: polly

无论实际响应如何,Polly 重试策略结果始终成功

我正在尝试利用Polly处理任意结果条件的能力https://github.com/App-vNext/Polly/#step-1b-optionally-specify-return-results-you-want-to-处理

在我的测试用例中,我使用RestSharp发出 HTTP 请求。这是我的示例代码:

var policy = Policy
    .HandleResult<IRestResponse>(r => r.Content.Contains("bla"))
    .Retry(2)
    .ExecuteAndCapture(() =>
        {
            IRestClient client = new RestClient("https://httpbin.org/anything");
            IRestRequest request = new RestRequest(Method.GET);
            var response = client.Execute(request);
            return response;
        });
Run Code Online (Sandbox Code Playgroud)

https://httpbin.org/anything的调用回响了一堆东西 - 确切的内容并不相关。正如您在谓词中看到的,我在结果正文中寻找字符串“bla”。

问题是,policy.Outcome总是成功的(policy.Outcome == OutcomeType.Successful),但“喇嘛”是不是在结果身体。

.net c# restsharp polly

4
推荐指数
1
解决办法
3076
查看次数

Polly 的 Policy.TimeoutAsync 不适用于异步上下文中的 PolicyWrap

这是一个完全有效的示例(复制/粘贴它并尝试一下,只需获取 Polly Nuget)

我有以下控制台应用程序代码,它向“ http://ptsv2.com/t/v98pb-1521637251/post ”上的 HTTP 客户端沙箱发出 POST 请求(您可以访问此链接“ http://ptsv2.com/ t/v98pb-1521637251 “查看配置或让自己成为一个“厕所”):

class Program
{
    private static readonly HttpClient _httpClient = new HttpClient()
        ; //WHY? BECAUSE - https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
    static void Main(string[] args)
    {
        _httpClient.BaseAddress = new Uri(@"http://ptsv2.com/t/v98pb-1521637251/post");
        _httpClient.DefaultRequestHeaders.Accept.Clear();
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));

        var result = ExecuteAsync("Test").Result;
        Console.WriteLine(result);
        Console.ReadLine();
    }

    private static async Task<string> ExecuteAsync(string request)
    {
        var response = await Policies.PolicyWrap.ExecuteAsync(async () => await _httpClient.PostAsync("", new StringContent(request)).ConfigureAwait(false));
        if (!response.IsSuccessStatusCode)
            return "Unsuccessful";
        return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
    }
}
Run Code Online (Sandbox Code Playgroud)

Http 客户端等待 4 秒,然后返回响应。

我已经设置了这样的策略( …

c# asynchronous timeout dotnet-httpclient polly

4
推荐指数
1
解决办法
5217
查看次数

Polly WaitAndRetryAsync 在一次重试后挂起

如果 HTTP 调用失败,我在非常基本的场景中使用 Polly 进行指数退避:

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    return await HandleTransientHttpError()
        .Or<TimeoutException>()
        .WaitAndRetryAsync(4, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt)))
        .ExecuteAsync(async () => await base.SendAsync(request, cancellationToken).ConfigureAwait(false));
}

private static PolicyBuilder<HttpResponseMessage> HandleTransientHttpError()
{
    return Policy
        .HandleResult<HttpResponseMessage>(response => (int)response.StatusCode >= 500 || response.StatusCode == System.Net.HttpStatusCode.RequestTimeout)
        .Or<HttpRequestException>();
}
Run Code Online (Sandbox Code Playgroud)

我有一个测试 API,它只是HttpListenerwhile(true). 目前,我正在尝试测试客户端在每次调用收到 500 时是否正确重试。

while (true)
{
    listener.Start();
    Console.WriteLine("Listening...");
    HttpListenerContext context = listener.GetContext();
    HttpListenerRequest request = context.Request;

    HttpListenerResponse response = context.Response;
    response.StatusCode = (int)HttpStatusCode.InternalServerError;

    //Thread.Sleep(1000 * 1); …
Run Code Online (Sandbox Code Playgroud)

.net c# polly exponential-backoff retry-logic

4
推荐指数
1
解决办法
4555
查看次数

如何使用 Polly 和取消令牌进行重试?

我对 Polly 很陌生,所以与我尝试做的方法相比,可能有一种完全不同的方法,那是完全可以的。

我的目标是这样的:

  1. token可能因超时或请求而被取消
  2. 永远重试,直到成功或被token取消。
  3. 当请求取消等待时应立即退出

尽管我使用的方法似乎缺少一些东西,并且可能有更好/更干净的方法来完成我想要的事情。我特别想到这一行.WaitAndRetryForever(retryAttempt => TimeSpan.Zero,。我觉得我应该能够通过retryDelay这里而不是TimeSpan.Zero,但如果我在请求取消时这样做,它不会返回,直到retryDelay完成等待,而不是像我想要的那样立即返回。

我确实看到 .Execute 看起来可以使用取消令牌执行某些操作,但我不知道如何使用它,所以如果这是我的答案,请忽略我的其他漫谈。

以防万一 Polly NuGet 开发人员看到这一点,我期望看到的是一个重载,因为WaitAndRetryForever它将取消令牌作为参数,以便在被取消时它可以立即返回。我犹豫是否将此作为正式建议,因为我对波莉来说太陌生了,我不确定这是否有意义。

这是我目前正在使用的方法:

internal static void Retry(Action action, TimeSpan retryDelay, CancellationToken token)
{
    try
    {
        Policy
            .Handle<IOException>()
            .WaitAndRetryForever(retryAttempt => TimeSpan.Zero,
                (ex, delay, context) =>
                {
                    Task.Delay(retryDelay, token).GetAwaiter().GetResult();
                    token.ThrowIfCancellationRequested();
                    //Log exception here
                })
            .Execute(() =>
            {
                token.ThrowIfCancellationRequested();
                action.Invoke();
            });
    }
    catch (OperationCanceledException)
    {
        //Log cancellation here
        throw;
    }
    catch (Exception ex)
    {
        //Log …
Run Code Online (Sandbox Code Playgroud)

c# polly

4
推荐指数
1
解决办法
7740
查看次数

使用 Polly 进行 HttpClient 单元测试

我正在寻找HttpClient对 a进行单元测试Polly RetryPolicy,并且我正在尝试找出如何控制响应的内容HTTP

我在客户端上使用了 a HttpMessageHandler,然后覆盖发送异步,这效果很好,但是当我添加 Polly 重试策略时,我必须使用 a 创建 HTTP 客户端的实例IServiceCollection,并且无法HttpMessageHandler为客户端创建 a。我尝试过使用,.AddHttpMessageHandler()但这会阻止轮询重试策略,并且只会触发一次。

这就是我在测试中设置 HTTP 客户端的方式

IServiceCollection services = new ServiceCollection();

const string TestClient = "TestClient";
 
services.AddHttpClient(name: TestClient)
         .AddHttpMessageHandler()
         .SetHandlerLifetime(TimeSpan.FromMinutes(5))
         .AddPolicyHandler(KYA_GroupService.ProductMessage.ProductMessageHandler.GetRetryPolicy());

HttpClient configuredClient =
                services
                    .BuildServiceProvider()
                    .GetRequiredService<IHttpClientFactory>()
                    .CreateClient(TestClient);

public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions
            .HandleTransientHttpError()
            .WaitAndRetryAsync(6,
                retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                onRetryAsync: OnRetryAsync);
}

private async static Task OnRetryAsync(DelegateResult<HttpResponseMessage> outcome, TimeSpan timespan, int retryCount, Context context)
{ …
Run Code Online (Sandbox Code Playgroud)

c# unit-testing dotnet-httpclient polly retry-logic

4
推荐指数
1
解决办法
9107
查看次数

在 Polly 重试尝试中获取完整的 URI?

我正在使用 Polly 重试 HttpClient 尝试:

\n
        services.AddHttpClient<JoinPackageApiClient>(jp => { jp.BaseAddress = new Uri(appSettings.JoinPackageWS.BaseUrl); })\n            .AddPolicyHandler(GetRetryPolicy(appSettings, serviceProvider))\n
Run Code Online (Sandbox Code Playgroud)\n

哪里 GetRetryPolicy

\n
 private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(AppSettings appSettings, ServiceProvider serviceProvider)\n        {\n            return HttpPolicyExtensions\n                .HandleTransientHttpError()\n                .OrResult(msg => msg.StatusCode != HttpStatusCode.OK)\n                .Or<TimeoutRejectedException>()\n                .Or<TaskCanceledException>()\n                .Or<OperationCanceledException>()\n\n                .WaitAndRetryAsync(appSettings.PollySettings.RetryAttempts, (retryAttempt, c) =>\n                {\n\n                 return TimeSpan.FromSeconds(2);\n                }, onRetry: (response, delay, retryCount, context) =>\n                {\n\n                   //\xe2\x96\x88how can I access the full(!) HttpClient's URI here ?\n                   //e.g. : https://a.com/b/c?d=1\n               \n                });\n        }\n
Run Code Online (Sandbox Code Playgroud)\n

问题:

\n

查看该onRetry参数,我想在该onRetry部分中记录完整的 URL …

c# dotnet-httpclient .net-core polly retry-logic

4
推荐指数
1
解决办法
932
查看次数

尝试包装 2 个 Polly 策略时出现转换错误

我正在尝试包装两个 Polly 策略并想要返回IAsyncPolicy,但它给出了错误,

从 Polly.Retry.RetryPolicy < System.Net.Http.HttpResponseMessage> 转换为 Polly.IAsyncPolicy

public static IAsyncPolicy CreateDefaultRetryPolicy()
    {
        var timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromSeconds(180));

        var waitAndRetryPolicy = Polly.Policy
                .Handle<HttpRequestException>()
                .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
                .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt)),
                (result, timeSpan, context) =>
                {
                });

        return Policy.WrapAsync(timeoutPolicy, waitAndRetryPolicy);
    }
Run Code Online (Sandbox Code Playgroud)

如何包装并返回?

c# timeout polly retry-logic policywrap

3
推荐指数
1
解决办法
1979
查看次数

调用 Polly ExecuteAsync 方法的正确方法是什么?

执行策略时,我看到有些人这样调用 ExecuteAsync:

...
.ExecuteAsync(async (ct) => await GetEmployeeAsync(employeeId, ct), cancellationToken);
Run Code Online (Sandbox Code Playgroud)

像这样:

...
.ExecuteAsync(ct => GetEmployeeAsync(employeeId, ct), cancellationToken);
Run Code Online (Sandbox Code Playgroud)

有什么区别以及应该使用哪一种?

c# task-parallel-library polly

3
推荐指数
1
解决办法
6523
查看次数

使用 Polly 在 ASP.NET Core 中重试请求时出现“流已被消耗”错误

我有一个 ASP.NET Core 3.1 Web API 服务,它正在接收 Web 请求,对其进行一些操作,然后将其传递到后端服务并同步返回响应。它工作正常,但我想为这些后端请求引入一些重试逻辑,以防出现一些问题。

我正在使用类型化的 HttpClient 并尝试使用 Polly 来实现重试逻辑: https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory#using-polly-with-ihttpclientfactory

当后端服务工作时,一切似乎都很好,但不幸的是,每当我的后端返回诸如 500 内部服务器错误之类的错误时,我都会收到以下异常:

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request.

System.Net.Http.HttpRequestException: An error occurred while sending the request.
 ---> System.InvalidOperationException: The stream was already consumed. It cannot be read again.
   at System.Net.Http.StreamContent.PrepareContent()
   at System.Net.Http.StreamContent.SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken)
   at System.Net.Http.HttpContent.CopyToAsync(Stream stream, TransportContext context, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnection.SendRequestContentAsync(HttpRequestMessage request, HttpContentWriteStream stream, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
   --- End of …
Run Code Online (Sandbox Code Playgroud)

c# polly asp.net-core

3
推荐指数
1
解决办法
8319
查看次数

Polly 重试不会关闭现有的 HttpClient 调用

我使用 Polly 来处理一些场景,例如请求限制和超时。这些策略直接添加到 Startup.cs 中,如下所示:

var retries = //applying the retries, let say I set to 25 times with 10s delay. Total 250s.

serviceCollection
    .AddHttpClient<IApplicationApi, ApplicationApi>()
    .AddPolicyHandler((services, request) => GetRetryPolicy<ApplicationApi>(retries, services));
Run Code Online (Sandbox Code Playgroud)

政策:

static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy<T>(List<TimeSpan> retries, IServiceProvider services)
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
        .WaitAndRetryAsync(retries,
            onRetry: (outcome, timespan, retryAttempt, context) =>
            {
                //do some logging
            }
}
Run Code Online (Sandbox Code Playgroud)

在 ApplicationApi.cs 中执行如下操作:

private readonly HttpClient _httpClient;
public ApplicationApi(HttpClient httpClient)
{
    _httpClient = httpClient;
}
       
public void CallApi()
{ 
      var …
Run Code Online (Sandbox Code Playgroud)

.net c# dotnet-httpclient .net-core polly

3
推荐指数
1
解决办法
2043
查看次数