我正在研究.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);
}
答案 0 :(得分:0)
您是否看过ConfigureHttpClient
的{{1}}扩展方法。它使您可以配置工厂正在创建的HttpClientFactory
。
您可以尝试以下方法-
HttpClient
它基于something I wrote,它在运行时更改请求中的标头标头。