3

我正在尝试使用新的 .NET Core 2.1 HttpClientFactory 实施 Polly Timeout 策略;但是,我似乎无法让超时发生。

我的ConfigureServices

// Configure polly policies
TimeoutPolicy<HttpResponseMessage> timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(5, TimeoutStrategy.Pessimistic);

// Configure platform service clients
services.AddHttpClient<IDiscoveryClient, DiscoveryClient>()
    .AddPolicyHandler(timeoutPolicy);

我的 POST 方法DiscoveryClient

public async Task<TResponse> PostXMLAsync<TResponse, TPostData>(string url, TPostData postData)
    where TResponse : ClientResponse
    where TPostData : ClientPostData
{
    HttpResponseMessage response = await httpClient.PostAsXmlAsync(url, postData);
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadAsAsync<TResponse>();
}

不幸的是,调用在默认的 100 秒后超时,而不是在 Polly 策略中定义的 5 秒后超时。

对我做错了什么有任何想法吗?

4

1 回答 1

0

首先让我们定义一个模拟服务器,它在 100 秒后响应 500:

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

现在,让我们看看IDiscoveryClientand 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

于 2021-01-15T18:00:16.720 回答