多个 HttpClientHandler 实例超时错误

Posted

技术标签:

【中文标题】多个 HttpClientHandler 实例超时错误【英文标题】:Time out errors with multiple HttpClientHandler instance 【发布时间】:2022-01-12 13:00:27 【问题描述】:

我们编写了一个与外部 API 连接的应用程序。您需要有一个 Token 才能与此 api 进行通信。每个用户的令牌必须是唯一的。要获取令牌,我们需要使用属于该用户的客户端证书调用端点。

我们通过对所有 API 请求使用 1 个静态 HttpClientHandler 实例来实现这一点。每个请求都使用给定的静态处理程序设置一个 HttpClient;并且只有客户端将被释放,处理程序将保持活动状态。 但是要获得token;我们需要将证书添加到处理程序。因此在获取token时;我们使用一个新的 HttpClientHandler 实例来获取令牌。获得令牌后,我们将释放客户端和处理程序实例。

现在很多调用都失败并出现以下错误:

连接尝试失败,因为连接方在一段时间后没有正确响应,或者连接失败,因为连接的主机没有响应 [ip]:443

大多数错误发生在我们获取 Token 时。但有时正常的 API 调用会因同样的错误而失败。

对方也研究过这个问题;他们给我们的最新结论是:在请求结束时,我们保持连接处于活动状态;因此该端口是为该连接保留的。但是,有时会尝试使用相同的端口从我们这边设置一个新请求(我猜是新连接)。有防火墙阻止/丢弃这个新请求;因为这个端口已经被使用了。这就是我们以这个超时错误结束的原因。

嗯,这是有道理的;我们无法控制连接使用的端口。但是为什么会这样呢?我有这样的理论,即问题在于静态处理程序(支持 10 个并行连接并保持此连接处于非活动状态,但仍处于活动状态)和可能认为端口空闲的第二个(或更多)其他处理程序的组合(因为那里不是此端口上的活动)可能会尝试建立与该端口的连接。但这只是一个理论;我找不到这方面的证据。

有没有人可以证实这个理论;或者也许给出其他解释为什么会出现这个问题?和/或是否有针对此问题的解决方案/解决方法?

【问题讨论】:

【参考方案1】:

您好,我认为您遇到了一个称为 Socket Exhaustion 的问题。尽管您对 HTTP 客户端进行了dispose(),但它使用的套接字仍将保留一段时间。为了防止这种情况发生,您需要一种机制来允许您重用 HttpClient 以及它们使用的底层套接字。

推荐的方法是使用 HttpClientFactory。该工厂将使用 HttpClients 构建一个池,并按需为您提供一个,同时为您维护客户端池。

更多信息可在 Microsoft Docs 网站上找到:https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests

【讨论】:

谢谢;但是据我所知,这个 Socket Exhaustion;您应该在 Windows 事件日志中出现此错误。这不应该是很多连接的问题吗?因为我们几乎在每次调用时都重用了处理程序;只是为了获得一个令牌,我们需要另一个 httpClientHandler 实例。 Netstat 声明最多 20 个到 api 的连接。但也许我弄错了;并且可以肯定;我会再次研究这个。

以上是关于多个 HttpClientHandler 实例超时错误的主要内容,如果未能解决你的问题,请参考以下文章

在c#中使用httpclienthandler使用一个参数发布多个值

Windows Phone 7上的超时httpClient

HttpClientHandler / HttpClient 内存泄漏

HttpClientHandler 抛出 PlatformNotSupportedException

如何在 .NET Core 中使用 HttpClientHandler 和 HttpClientFactory

JBOSS Server 实例化超时