在 kestrel 中自托管的 signalr 中的最大并发请求数

Maximum concurrent requests in signalr self hosted in kestrel

我开发的应用程序遇到了一个奇怪的问题。该应用程序是在 Kestrel 上托管 AspNetCore 2.0 运行 的 windows 服务。此应用程序通过充当代理的 IIS 站点接收请求。

在这个应用程序中,我还使用 Microsoft.AspNetCore.Owin 集成的信号 2.2.2。一切正常,直到我检测到应用程序没有响应请求。

同一台机器上使用同一 IIS 服务器作为代理的其他应用程序工作正常。重新启动为网站提供服务的应用程序池暂时解决了问题。

问题再次浮出水面,通过监控信息挖掘应用程序似乎在同一台机器上有 400 个 signalr SSE 连接时挂起。这似乎是合理的,因为我发现默认情况下 OWIN 将并发请求数限制在 100 * number of cpus。 (请注意,同一台机器上的站点每分钟可以毫不费力地处理 5000 个请求,但这些请求不像 SignalR 那样是长期存在的请求)

问题是在 AspNetCore 中托管 Owin 时,我似乎无法找到相同的选项。有人知道这是否可以解决问题吗?正确的设置是什么?

编辑:我相当确定问题是由同时打开的 SignalR 连接数引起的,因为在 Javascript 中禁用它后问题就消失了。

第二次编辑:signalr 似乎不是 cuplrit,因为在测试和生产中使用 crank 对站点进行负载测试一直工作到 5000 个并发连接,这是默认的 IIS 限制我觉得很好

这可能是问题所在,但不太可能。在 dotnet 核心中托管时,您可能正在使用 Kestrel 作为 Web 服务器实现,要切换这些限制(例如并发连接),您可以使用 KestrelServerLimits class,如 Microsoft article.

中所述

KestrelServerLimits 应该不会给您带来任何问题,因为 ConcurrentConnections 的默认值是无限的。

经过反复试验,我已经能够识别并纠正问题,但这并非易事,所以如果其他人偶然发现同样的问题,我将留下这个答案。

禁用 SignalR 没有解决问题,但它出现的频率降低了。

多亏了服务器和 IIS 上的监控,我观察到当站点的连接数开始快速增长时问题就出现了。该系统主要向其他服务发出请求,因此它没有数据库,也没有昂贵的计算。

检查代码我发现存在三个问题:

  • 为每个请求创建了一个新的 HttpClient,它可以耗尽请求之间未重复使用的套接字 blog2 blog3
  • 默认情况下,httpClient 上对单个域的并发连接数有最大限制,此限制默认设置为 2 (!!!) blog4
  • 代码同步等待对另一个系统的每个 Web 请求(此程序是从从未显示此问题的 mvc4 站点移植的)。这在 MVC 中运行良好,但 asp.net 核心对此非常敏感,因为它会迅速耗尽所有可用线程,并且因为线程池以核心数量开始,它们将很快耗尽,使所有请求等待。可以使用 ThreadPool.SetMaxThreads(Int32, Int32) 作为临时权宜之计解决方案增加此值,但唯一的解决方案是将所有调用转换为异步调用。

一旦所有调用都 mde 异步,问题就再也没有出现过。基本上问题是由于线程池饥饿和 aspnet 核心对它与 MVC 的敏感性。 Here 你可以找到一个很好的解释和使用 PerfView 的检测方法。