【问题标题】:Using Polly to retry on different Urls after failing retries重试失败后使用 Polly 重试不同的 Url
【发布时间】:2019-07-31 22:03:51
【问题描述】:

我正在 .Net Core 中进行概念验证,并且是 polly 的新手,并且努力了解如何以定义重试策略的方式对其进行配置,但是在此失败后,我们切换到不同的 url 和重试(可能有很多,可用的 Url 列表是动态的)

我的偏好是使用此处描述的 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);
        }

【问题讨论】:

    标签: c# .net-core polly


    【解决方案1】:

    你看过HttpClientFactoryConfigureHttpClient扩展方法吗。它允许您配置工厂正在创建的HttpClient

    这是你可以尝试的 -

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMemoryCache();
        services.AddSingleton<IMyUrlList, MyUrlList>();
    
        services.AddHttpClient("RemoteServer", client =>
        {
            client.DefaultRequestHeaders.Add("Accept", "application/json");
        }).ConfigureHttpClient((serviceProvider, client) =>
        {
            IMyUrlList myUrlList = serviceProvider.GetService<IMyUrlList>();
            client.BaseAddress = myUrlList.NextUrl();
        });
    
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-14
      • 1970-01-01
      • 2018-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多