重试失败后,使用Polly重试不同的Urls

时间:2019-07-31 22:03:51

标签: c# .net-core polly

我正在研究.Net Core中的概念验证,并且对Polly还是很陌生,并且难以理解如何以定义重试策略的方式对其进行配置,但是在失败之后,我们切换到其他URL,并对此重试(可能有很多,并且可用的Urls列表是动态的)

我的偏好是使用HttpClientFactory和Typed Clients,如此处所述 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.1#typed-clients

我看过 https://github.com/App-vNext/Polly/issues/199

https://github.com/App-vNext/Polly/issues/591

但是无法看到如何将其应用于动态列表以及HttpClientFactory / Typed Client方法内

// Attempting to enable dynamic clients
// https://github.com/App-vNext/Polly/issues/199
// https://github.com/App-vNext/Polly/issues/591 using HttpClientfactory


 services.AddHttpClient<IAppointmentServiceClient, AppointmentServiceClient>()
                .ConfigureHttpClient((serviceProvider, client) =>
{
                    var serverList = ServiceRegistration.LocateServiceList("AppointmentService").Result;
                    var random = new Random();
                    int index = random.Next(serverList.Count);
                    var baseAddress = new Uri($"http://{ serverList[index]}");


                    client.BaseAddress = baseAddress;
                })
                .AddPolicyHandler(GetRetryPolicy())

                //.AddPolicyHandler(GetCircuitBreakerPolicy());
                .AddPolicyHandler((sp, req, key) =>
                {
                    return GetCircuitBreakerPolicy();
                },
                GetPolicyKey
                );
}


static string GetPolicyKey(HttpRequestMessage httpRequestMessage)
{
 return httpRequestMessage.RequestUri.Authority;
}


static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
       return HttpPolicyExtensions
              .HandleTransientHttpError()
              .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
              .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                onRetryAsync: async (outcome, timespan, retryCount, context) => {
                    context["RetriesInvoked"] = retryCount; // allows us to capture the reties downstream, potential for extra logging 

                });

}

static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
        {
            return HttpPolicyExtensions
                .HandleTransientHttpError()
                .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30), 
                    onBreak: (ex, breakDelay, context) =>
                    {

                    },
                    onReset: (context)=> 
                    {

                    },
                    onHalfOpen: () => { }
                );
}

实际通话只是

public AppointmentServiceClient(HttpClient httpClient)
{
    _apiClient = httpClient;
}

public async Task<IEnumerable<AppointmentEntity>> GetResourceAppointments(string resourceId, DateTimeOffset date)
        {

            var url = GetResourceAppointmentsUrl(resourceId, date);

            var context = new Polly.Context();
            //context["baseUrls"] = _serverList;

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
            request.SetPolicyExecutionContext(context);
            var response = await _apiClient.SendAsync(request);

            context = response.RequestMessage?.GetPolicyExecutionContext(); // (if not already held in a local variable)
            //if (context?.TryGetValue("RetriesInvoked", out int? retriesNeeded) ?? false)
            //{
            //    // Do something with int? retriesNeeded
            //}


            response.EnsureSuccessStatusCode();
            var appointmentResponse = await response.Content.ReadAsStringAsync();

            return JsonConvert.DeserializeObject<IEnumerable<AppointmentEntity>>(appointmentResponse);
        }

1 个答案:

答案 0 :(得分:0)

您是否看过ConfigureHttpClient的{​​{1}}扩展方法。它使您可以配置工厂正在创建的HttpClientFactory

您可以尝试以下方法-

HttpClient

它基于something I wrote,它在运行时更改请求中的标头标头。