0

我正在尝试开始使用 Polly。请参阅下面的我的 Startup 课程:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services//.AddCustomMvc(Configuration)
             //.AddCustomAuthentication(Configuration)
             .AddHttpServices()
             .AddHttpClientServices(Configuration)
        .AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        //This is not changed.
    }
}

static class ServiceCollectionExtensions
{
    public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        //register delegating handlers
        services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
        services.AddTransient<HttpClientRequestIdDelegatingHandler>();
        services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(TimeSpan.FromMinutes(5));
        services.AddHttpClient<IValuesService, ValuesService>()
               .SetHandlerLifetime(TimeSpan.FromMinutes(5))  //Sample. Default lifetime is 2 minutes
               .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
               .AddPolicyHandler(GetRetryPolicy())
               .AddPolicyHandler(GetCircuitBreakerPolicy());

        return services;
    }

    public static IServiceCollection AddHttpServices(this IServiceCollection services)
    {
        services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddHttpClient<IValuesService, ValuesService>()
            .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
            .AddPolicyHandler(GetRetryPolicy())
            .AddPolicyHandler(GetCircuitBreakerPolicy());
        return services;
    }


    static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        return HttpPolicyExtensions
          .HandleTransientHttpError()
          .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
          .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

    }
    static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
    {
        return HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
    }
}

我正在使用这样的 HTTPClient:

  public class ValuesService : IValuesService
        {
            private readonly HttpClient _apiClient;

            public ValuesService(HttpClient httpClient)
            {
                _apiClient = httpClient;

            }

            public async Task<string> GetValue()
            {
                var uri = API.Values.GetValues("http://localhost:55461/api");
                //The line below throws a SocketException
                var responseString = await _apiClient.GetStringAsync(uri);

                return responseString;
            }
        }

GetValue() 尝试访问 Web API 一次,然后失败。为什么它不尝试按照配置多次访问 Web API?

4

1 回答 1

0

The policy specification

HttpPolicyExtensions.HandleTransientHttpError()

handles the faults:

  • HttpRequestException
  • status codes >= 500
  • status code 408

Reference: Polly wiki on Polly-and-HttpClientFactory

This mirrors the faults handled by the default HttpClientFactory implementation .AddTransientHttpErrorPolicy(...) extension method.

To handle SocketException additionally, you can extend the policies similarly to the example in the Polly-HttpClientFactory documentation. For example:

static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions
      .HandleTransientHttpError()
      .Or<SocketException>()
      .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
      .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

}
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .Or<SocketException>()
        .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}

(Based on comments to the original question about SocketException being raised and retries not occurring, this answer explains how to make the policies handle SocketException.)

于 2018-08-06T20:35:31.967 回答