HttpClient轮询超时策略



get请求等待超时的时间比timeoutPolicy要长。

  • 有人知道为什么会发生这种事吗
  • 为什么请求没有在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);
}

我想我已经玩够了,我知道发生了什么,所以我有信心现在可以回答这个问题。

当您使用TimeoutStrategy.Optimistic-Polly策略调用async任务时,您传递的是CancellationToken,并且基本上相信CancellationToken将被调用以在超时情况下结束任务。

TimeoutStrategy.Pesimistic策略的行为不同,后者被设计为能够终止不通过CancellationToken回调的同步任务。

虽然主执行线程不会被另一个线程上运行的异步任务阻塞,但重要的是要记住,该任务确实能够阻塞自己的线程。

例如,如果异步任务要调用Thread.Sleep(1000),那么它的线程将被阻塞一秒钟。这又意味着在块的持续时间内不能调用CancellationToken

在这种情况下,我相信会发生长时间运行的操作,例如第一次查找主机名的DNS记录,或者任何其他阻塞操作,这些操作基本上会阻塞线程90毫秒。

因此,即使任务知道它需要在30ms标记处中止,它也需要等待线程可用,然后才能真正调用取消,直到大约90ms左右才会发生。

这种返回超时的延迟似乎只在每次域解析的第一次出现,所以我认为这与名称服务器缓存和DNS解析有关,因为后续调用似乎更有效地遵守超时。尽管断言任何直接的根本原因在很大程度上都是猜测。

相关内容

  • 没有找到相关文章

最新更新