简体   繁体   English

HttpClient Polly 超时策略

[英]HttpClient Polly Timeout Policy

The get request is waiting longer than the timeoutPolicy to timeout.获取请求等待超时的时间比timeoutPolicy长。

  • Does anyone have any idea why this is happening?有谁知道为什么会这样?
  • Why does the request not timeout at 30ms?为什么请求没有在 30ms 超时?
var timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(30), TimeoutStrategy.Optimistic);
var watch = new Stopwatch();
try
{
    watch.Start();
    var httpResponse = await timeoutPolicy.ExecuteAsync(
        async ct => await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "https://google.com"), ct),
        CancellationToken.None
    );
    watch.Stop();
    Console.WriteLine("request took " + watch.ElapsedMilliseconds);
}
catch (Exception e)
{
    watch.Stop();
    Console.WriteLine("timeout took " + watch.ElapsedMilliseconds);
    Console.WriteLine(e.Message);
}

I think I've played around with it enough that I know what's going on, So I feel confident that I can now answer the question.我想我已经玩够了,我知道发生了什么,所以我有信心我现在可以回答这个问题。

When you invoke the async task with TimeoutStrategy.Optimistic Polly strategy, you are passing in a CancellationToken and essentially trusting that the CancellationToken will be invoked to end the task in a timeout scenario.当您使用TimeoutStrategy.Optimistic Polly 策略调用async任务时,您传递的是CancellationToken并且基本上相信CancellationToken将被调用以在超时情况下结束任务。

Unlike the behavior with the TimeoutStrategy.Pesimistic strategy which is designed to be able to terminate a syncronous task which does not callback via the CancellationToken .TimeoutStrategy.Pesimistic策略的行为不同,后者旨在能够终止不通过CancellationToken回调的同步任务。

While your main execution thread is not blocked by an asyncronous task running on another thread, it's important to remember that the task is indeed able to block it's own thread.虽然您的主执行线程不会被另一个线程上运行的异步任务阻塞,但重要的是要记住该任务确实能够阻塞它自己的线程。

For example, If an async task were to call Thread.Sleep(1000) then it's thread would be blocked for a second.例如,如果异步任务要调用Thread.Sleep(1000)那么它的线程将被阻塞一秒钟。 Which in turn means that the CancellationToken cannot be invoked for the duration of the block.这反过来意味着在块的持续时间内无法调用CancellationToken

In this scenario I believe that long running operations such as looking up the DNS record for a hostname the first time, or any other blocking operation is occurring which is essentially blocking the thread for 90ms.在这种情况下,我相信长时间运行的操作,例如第一次查找主机名的 DNS 记录,或任何其他阻塞操作正在发生,这基本上会阻塞线程 90 毫秒。

As such, even though the task knows that it needs to be aborted at the 30ms mark, it need to wait for the thread to be available before it can actually invoke the cancellation, which doesn't occur until about 90ms or thereabouts.因此,即使任务知道它需要在 30ms 标记处中止,它也需要等待线程可用,然后才能实际调用取消,这直到大约 90ms 左右才会发生。

This delay in returning a timeout only seems to occur the first time for each domain resolution, so I presume this is related to nameserver caching and DNS resolution as subsequent calls seem to honor the timeout more efficiently.这种返回超时的延迟似乎只发生在每个域解析的第一次,所以我认为这与名称服务器缓存和 DNS 解析有关,因为后续调用似乎更有效地遵守超时。 Although asserting any direct root cause is largely speculation.尽管断言任何直接的根本原因在很大程度上是猜测。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM