HttpClient 分别设置连接超时和响应超时时间。

huangapple go评论65阅读模式
英文:

Separate timeouts for connection and response on HttpClient

问题

有多种方法可以使 HttpClient 调用超时或被取消:通过设置 HttpClient.Timeout 属性,通过传递 CancellationToken,使用自定义的 HttpMessageHandler 等。所有这些方法的问题是,无论是根本无法连接到服务器还是需要更长时间来响应,超时都会发生并且调用被取消。

我要实现的行为已经存在的示例是 Postman:
例如,当我的 ASP.NET Core Web API 没有运行时,通过 Postman 发送请求后,它会在大约 5 秒后停止。但当我的 Web API 运行时,我通过 Postman 发送请求,然后在我的代码中设置断点或添加延迟等,那么 Postman 将等待其设置中指定的毫秒数(超过 5 秒)。

这就是我想要实现的效果。我想要为我的 HTTP 请求设置两个不同的超时时间:一个用于等待与服务器的连接,另一个用于等待响应。最理想的情况是,当等待响应时,如果与服务器的连接中断,调用也会被取消。在 C# 中(使用 .NET 6),是否有可能实现这样的功能,如果可以,如何实现?

英文:

There are multiple ways for HttpClient calls to timeout/be cancelled: by setting the HttpClient.Timeout property, by passing in a CancellationToken, using a custom HttpMessageHandler, etc. The problem with all these approaches is that the timeout is met and the call is cancelled regardless of if the server couldn't be reached at all or if it just takes longer to respond.

An existing example of the behavior I want to implement is Postman:
When (for this example) my ASP.NET Core Web API is not currently running and I send a request via Postman it stops right after just 5 seconds or so. But when my Web API runs, I send a request via Postman and then hit a breakpoint in my code or add a delay or something, than Postman will wait the amount of milliseconds that was specified in its settings (= more than 5 seconds).

And that's kind of what I want to get to work. To have two different timeouts for my HTTP requests. One for waiting for a connection to the server and one for waiting for its response. Perfect would be if the call would also be cancelled when the connection to the server is interrupted while waiting for the response. Is something like this possible in C# (using .NET 6) and if yes, how?

答案1

得分: 7

当实例化HttpClient时,您可以提供System.Net.Http.HttpMessageHandler的实现,我相信默认实现是SocketsHttpHandler

SocketsHttpHandler上,您可以提供连接超时。

var handler = new SocketsHttpHandler
{
    ConnectTimeout = TimeSpan.FromSeconds(5)
};

var client = new HttpClient(handler);

// 正常操作...

我更喜欢这种方法,而不是使用健全性检查,因为不能保证第一次调用成功后第二次调用也会成功。

英文:

When instantiating HttpClient, you're able to provide an implementation of System.Net.Http.HttpMessageHandler, I believe the default implementation is SocketsHttpHandler.

On the SocketsHttpHandler you're able to provide a connection timeout.

var handler = new SocketsHttpHandler
{
    ConnectTimeout = TimeSpan.FromSeconds(5)
};

var client = new HttpClient(handler);

// stuff as usual...

I prefer this to using a sanity check as there's no guarantee that if the first call succeeds that the second one will.

答案2

得分: 1

看起来您可以通过将SocketsHttpHandler的实例传递给HttpClient的构造函数来实现您的需求。

SocketsHttpHandler具有ConnectTimeout属性,如果在指定的持续时间内未建立连接,它将在HttpClient中引发超时。

有关在HttpClient中设置超时的更多详细信息,请参阅Microsoft的官方文档。

英文:

Looks like you can achieve what you want by passing an instance SocketsHttpHandler of to the constructor of HttpClient.

SocketsHttpHandler has a ConnectTimeout property which will cause a timeout in HttpClient if a connection is not established before the specified duration elapses.

See the official Microsoft documentation on setting Timeouts in HttpClient for more details.

答案3

得分: 0

如果我没有理解错,我会在我管理的一个关键服务中通过进行健全性检查来解决这个问题。

这个健全性检查由API中的一个样本状态方法组成,返回200。所以对于每个我需要快速答复的关键调用,我都进行了并行的健全性检查。因此,对于服务/服务器的检查和对于操作本身的检查,我都进行了两次服务调用。这样我就可以处理我正在处理的超时类型,服务器是否已经停止,或者操作是否延迟。

英文:

If I don't understand you wrong, I resolve this issue in a critital service that I manage with a sanity check.

The sanity check is compose by an sample status method in the API that returns 200. So for every critital call that I need a quick answer, I made a parallel sanity check. So two calls to the service: one for check the service/server and another one for the action itself. In this way I can handle what kind of timeout I'm working of, if server is gone or if action is delayed.

huangapple
  • 本文由 发表于 2023年3月9日 21:49:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75685512.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定