在 ASP.NET 核心应用程序中使用多个 HttpClient 对象

Using multiple HttpClient objects in an ASP.NET Core application

当有多个客户(公司)使用 ASP.NET 核心应用程序并且必须在 ASP.NET 应用程序中维护具有相应客户端证书的单独 HttpClient 实例时,最佳应用程序设计是什么对于这些公司中的每一个?

首先,关于申请的一些重要事实:

据我所知,为每次调用外部 Web 服务创建新的 HttpClient 对象并不是最佳做法。我考虑过 HttpClientFactory,但在我的例子中,每个 HttpClient 对象都必须包含公司相应的客户端证书。我知道 ASP.NET Core 支持命名的 HttpClient 来为每个公司维护单独的 HttpClient,但是据我所知,这个命名的客户端只能在 Startup class 中创建。这还不够,因为当 ASP.NET 应用 运行 时,可以随时注册新公司,当应用 运行 时,公司可以上传新证书,从而使现有命名客户端无效,等等。

我正在考虑为每个公司维护一个包含一个 HttpClient 对象的静态列表。当发起对公司的第一个请求时,将使用相应的客户端证书创建新的 HttpClient 并将其添加到此列表中。对于来自同一公司(或办公室)的所有后续请求,相应的 HttpClient 从提到的静态列表中获取并重新使用。当然,我必须在公司的 HttpClient 实例上建立一些锁定,以便在同一公司同时发出请求时它不会中断。我对这种设计的一个担忧是,可能有几百家公司,而这个 http 客户端列表可能会很长。

您还有什么想法或建议吗?

I am considering maintaining a static list containing one HttpClient object for each company.

在高层次上,我认为每个公司一个实例是正确的方法,但魔鬼在(实施)细节中。

Of course, I would have to establish some locking..

如果您使用的是专为此类用途而构建的类型,则不会。 ConcurrentDictionary, and specifically its GetOrAdd method,将为您提供一个键控存储机制,其中项目是延迟创建的,并且是线程安全和无锁的。

One concern I have with this design is that there might be couple of hundred companies and this list of http clients can be quite long.

我不知道您是否需要开始担心的具体数字(我相信取决于 OS 和硬件),但至少根据 the article that made the HttpClient singleton advice famous,它在数千,而不是数百。

"In the production scenario I had the number of sockets was averaging around 4000, and at peak would exceed 5000, effectively crushing the available resources on the server, which then caused services to fall over. After implementing the change, the sockets in use dropped from an average of more than 4000 to being consistently less than 400, and usually around 100."

不过,如果这是一个问题,您可以做的一件事就是让那些缓存的 HttpClient 实例偶尔过期。 (这也应该减轻 that other famous problem.) Unfortunately, ConcurrentDictionary doesn't provide that capability out of the box. MemoryCache does, but doesn't directly support the lazy GetOrAdd semantics like ConcurrentDictionary. For the best of both worlds, have a look at LazyCache.