0

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

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

现在很多电话都因以下错误而失败:

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

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

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

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

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

4

1 回答 1

1

何,我认为您面临一个称为 Socket Exhaustion 的问题。虽然你做dispose()了 HTTP Client,但它使用的套接字仍然会保留一定的时间。为了防止这种情况,您需要一种机制来允许您重用 HttpClients 以及它们使用的底层套接字。

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

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

于 2021-12-07T12:51:55.897 回答