Сначала давайте определим фиктивный сервер, который отвечает 500 через 100 секунд:
const string address = "http://localhost:9000";
var delay = TimeSpan.FromSeconds(100);
var server = WireMockServer.Start(new WireMockServerSettings { Urls = new[] { address } });
server
.Given(Request.Create().WithPath("/").UsingPost())
.RespondWith(Response.Create().WithDelay(delay).WithStatusCode(500));
Для этого я использовал WireMock.Net.
Теперь посмотрим на IDiscoveryClient
и DiscoveryClient
:
interface IDiscoveryClient
{
Task<TResponse> SendRequest<TResponse, TPostData>(string url, TPostData data);
}
class DiscoveryClient : IDiscoveryClient
{
private readonly HttpClient httpClient;
public DiscoveryClient(HttpClient httpClient) => this.httpClient = httpClient;
public async Task<TResponse> SendRequest<TResponse, TPostData>(string url, TPostData data)
{
var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8);
var response = await httpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();
var rawData = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TResponse>(rawData);
}
}
class TestRequest { public string Content { get; set; } }
class TestResponse { public string Data { get; set; } }
Я использовал json вместо xml, но с точки зрения вопроса это неважно.
И, наконец, подключим DI и сделаем запрос:
AsyncTimeoutPolicy<HttpResponseMessage> timeoutPolicy =
Policy.TimeoutAsync<HttpResponseMessage>(5, TimeoutStrategy.Pessimistic);
IServiceCollection services = new ServiceCollection();
services.AddHttpClient<IDiscoveryClient, DiscoveryClient>()
.AddPolicyHandler(timeoutPolicy);
ServiceProvider serviceProvider = services.BuildServiceProvider();
var client = serviceProvider.GetService<IDiscoveryClient>();
Stopwatch sw = Stopwatch.StartNew();
try
{
TestResponse res = await client.SendRequest<TestResponse, TestRequest>(address, new TestRequest { Content = "Test"});
}
catch (TimeoutRejectedException ex)
{
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
Напечатанный результат будет примерно таким:
00:00:05.0296804
Хорошо то, что он также работает со стратегиями Optimistic
и Pessimistic
.
person
Peter Csala
schedule
15.01.2021
await httpClient.PostAsXmlAsync(url, postData)
или вawait response.Content.ReadAsAsync<TResponse>()
? Как ты видишь тайм-аут? В журналах, или вы видите тайм-аут, выданный как исключение из любой из этих двух строк кода? - person mountain traveller   schedule 14.07.2018await httpClient.PostAsXmlAsync(url, postData)
требуется 100 секунд для завершения, а затем я получаюHttpRequestException: Response status code does not indicate success: 500 (Internal Server Error).
отresponse.EnsureSuccessStatusCode();
. Известно, что служба, которую я вызываю, время от времени делает это, поэтому я хотел реализовать политику тайм-аута Polly. - person wdspider   schedule 16.07.2018TimeoutStrategy.Optimistic
? HttpClientFactory - person mountain traveller   schedule 16.07.2018TimeoutStrategy.Optimistic
, похоже, не имеет значения. Я создал демонстрацию здесь: gist.github.com/wdspider/a1cf8328db54e06cd то, что я звоню, не является публичным; поэтому я просто добавил 20-секундную задержку вClientLoggingHandler
, что должно быть приличной симуляцией. - person wdspider   schedule 16.07.2018await Task.Delay(...)
выполняется до (является «снаружи», с точки зрения вложенности)TimeoutPolicy
; т.е. политика тайм-аута не регулирует задержку. Измените его наservices....AddPolicyHandler(timeoutPolicy).AddHttpMessageHandler<ClientLoggingHandler>();
, и тайм-аут сработает. Помогает ли эта информация оригинальному делу? - person mountain traveller   schedule 17.07.2018services.AddHttpClient(typeof(T).Name).AddPolicyHandler(GetPollyPolicies(retryCount, timeoutSeconds));
где, когда я комбинирую этоwaitAndRetryPolicy.WrapAsync(timeoutPerTryPolicy);
Когда я получаю httpClient от CreateClient, я смотрю на тайм-аут, который по умолчанию установлен на100
секунды. @mountaintraveller - person vsarunov   schedule 06.08.2020