是啥限制了我的 ASP.NET 应用程序可以与 Web 服务建立的同时连接数?

Posted

技术标签:

【中文标题】是啥限制了我的 ASP.NET 应用程序可以与 Web 服务建立的同时连接数?【英文标题】:What is limiting the # of simultaneous connections my ASP.NET application can make to a web service?是什么限制了我的 ASP.NET 应用程序可以与 Web 服务建立的同时连接数? 【发布时间】:2011-12-12 14:06:56 【问题描述】:

我有一个 ASP.NET 4.0 应用程序在 64 位 Windows Server 2008 R2 Enterprise 计算机上运行在 IIS 7.5 上,具有大量 RAM、CPU、磁盘等。

对于每个 Web 请求,ASP.NET 应用程序都会连接到在同一台机器上运行的后端 Web 服务(通过原始套接字)。

问题:似乎有一些东西限制了与后端 Web 服务的同时连接数。令人怀疑的是,并发连接数达到了 16 个。

我发现这篇来自 Microsoft 的重要文章解释了如何调整 IIS 的设置以适应发出大量 Web 服务请求的 ASP.NET 应用程序:http://support.microsoft.com/?id=821268#tocHeadRef

我遵循了文章的推荐,但仍然没有运气。特别有趣的设置是maxconnection设置,我什至碰到了999。

您知道其他可能会限制连接吗?

注意:当我将 IIS 从组合中剔除并让客户端直接连接到后端 Web 服务时,它会很高兴地打开我需要的任意数量的连接,所以我肯定后端不是瓶颈。它必须是 IIS/ASP.NET-land 中的东西。

这是machine.config 的相关部分,我确信应用程序正在读取它(通过appcmd.exe 验证):

<system.web>
    <processModel autoConfig="false" maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50" />
    <httpRuntime minFreeThreads="176" minLocalRequestFreeThreads="152"/>

    <httpHandlers />

    <membership>
        <providers>
            <add name="AspNetSqlMembershipProvider"
                type="System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                connectionStringName="LocalSqlServer"
                enablePasswordRetrieval="false"
                enablePasswordReset="true"
                requiresQuestionAndAnswer="true"
                applicationName="/"
                requiresUniqueEmail="false"
                passwordFormat="Hashed"
                maxInvalidPasswordAttempts="5"
                minRequiredPasswordLength="7"
                minRequiredNonalphanumericCharacters="1"
                passwordAttemptWindow="10"
                passwordStrengthRegularExpression="" />
        </providers>
    </membership>

    <profile>
        <providers>
            <add name="AspNetSqlProfileProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Profile.SqlProfileProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </profile>

    <roleManager>
        <providers>
            <add name="AspNetSqlRoleProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add name="AspNetWindowsTokenRoleProvider" applicationName="/"
                type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </roleManager>
</system.web>
<system.net>
    <connectionManagement>
        <add address="*" maxconnection="999"/>
    </connectionManagement>
</system.net>

【问题讨论】:

@DanB 有一个很好的观点 - 你如何测量并发连接数? @JeremyMcGee 我正在通过在服务器上运行 TCPView 来测量并发连接数,以查看 IIS 工作进程建立了多少后端连接。 Web 客户端是在独立机器上运行还是在同一台机器上运行? (检查是否存在客户端限制。) @JeremyMcGee 分离机器。每台机器 1 个客户端-服务器连接。此外,我们知道网络上的某个地方没有任何限制,因为当我们直接访问后端(也发生在 HTTP 上)时,我们不会遇到瓶颈。 Rob,你有没有找到一个明确的解决方案? 【参考方案1】:

我意识到这个问题可能很老了,但你说后端在同一台服务器上运行。这意味着在不同的端口上,可能不是默认端口 80。

我了解到,当您使用“connectionManagement”配置元素时,如果端口号不同于默认的 80,则需要指定端口号。

链接:maxConnection setting may not work even autoConfig = false in ASP.NET

其次,如果您选择使用默认配置 (address="*") 扩展您自己的后端特定值,您可以考虑将特定值放在首位!否则,如果发出请求,* 首先匹配并采用默认的 2 个连接。就像您在 web.config 中使用该部分一样。

链接:<remove> Element for connectionManagement (Network Settings)

希望对某人有所帮助。

【讨论】:

【参考方案2】:

在进行性能测试时,我采用的衡量标准是 RPS,即服务器在可接受的延迟内每秒可以处理多少个请求。

理论上,一台服务器只能同时运行与其上核心数量一样多的请求。

看起来问题不在于 ASP.net 的线程模型,因为它可能服务于数千个 rps。似乎问题可能出在您的应用程序上。您是否使用任何同步原语?

还有你的网络服务的延迟是多少,它们响应速度是否很快(在微秒内),如果不是,那么你可能需要考虑异步调用,所以你最终不会阻塞

如果这没有产生什么结果,那么您可能需要使用 Visual Studio 或 Redgate Profiler 来分析您的代码

【讨论】:

【参考方案3】:

这里提供的大多数答案都是针对后端 Web 服务的传入请求数,而不是您可以从 ASP.net 应用程序发出的传出请求数您的后端服务。

在此处限制您的请求率的不是您的后端 Web 服务,而是您的调用应用程序愿意与同一端点(同一 URL)建立的打开连接数。

您可以通过将以下配置部分添加到您的 machine.config 文件中来消除此限制:

<configuration>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="65535"/>
    </connectionManagement>
  </system.net>
</configuration>

如果您想要 50 或 100 个并发连接,您当然可以选择一个更合理的数字。但上述内容将其打开至最大值。您还可以为上面的开放限制规则指定一个特定的地址,而不是表示所有地址的“*”。

MSDN Documentation for System.Net.connectionManagement

Another Great Resource for understanding ConnectManagement in .NET

希望这能解决您的问题!

编辑: 糟糕,我确实看到您在上面的代码中提到了连接管理。我将留下我的上述信息,因为它与未来有同样问题的询问者有关。但是,请注意目前在最新的服务器上有 4 个不同的 machine.config 文件!

.NET Framework v2 在 32 位和 64 位下运行,.NET Framework v4 也在 32 位和 64 位下运行。根据您为应用程序池选择的设置,您可以使用这 4 个不同的 machine.config 文件中的任何一个!请检查通常位于此处的所有 4 个 machine.config 文件:

C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config

【讨论】:

是的,我覆盖了那个基础。无论如何,谢谢@BenSwayne!我确认我修改了正确的machine.config(64 位 4.0)。 @RobSobers:在这种情况下,我会对实现代码有点怀疑。也许您的线程用完了或其他什么?您可以将您的 TcpClient Web 服务调用代码放入控制台应用程序中,看看您是否可以获得更好的请求率?这将证明它是 IIS 特定配置还是更广泛的 .NET 配置或您的代码。 这条线是否进入客户端机器? 谢谢,您的设置与来自codeproject.com/Articles/133738/… 的 processModel twekaing 相结合,修复了“ISAPI 'C:\windows\Microsoft.Net\Framework\v2.0.050727\aspnet_isapi.dll' 报告为不健康的以下原因:“检测到死锁”问题 @BenSwayne 同样的概念是否也适用于 SMTP 连接?我正在设计一个批量电子邮件发送应用程序,所以这个 ConnectionManagement 属性在发送批量邮件时也会有用吗(对 mail.send 函数使用多线程)?【参考方案4】:

您可能正在使用基于 WCF 的 Web 服务引用吗?默认情况下,ServiceThrottlingBehavior.MaxConcurrentCalls 为 16。

您可以尝试更新服务引用行为的 &lt;serviceThrottling&gt; 元素

<serviceThrottling
    maxConcurrentCalls="999" 
    maxConcurrentSessions="999" 
    maxConcurrentInstances="999" />

(请注意,我建议使用上述设置。)有关如何配置适当的&lt;behavior&gt; 元素的更多信息,请参阅MSDN。

【讨论】:

我希望我们是,但我们不是。正在使用的服务在另一台机器上的 Apache/Python/mod_wsgi 中运行,正如 Rob 所说,这显然不是问题。 服务参考在客户端。您的客户如何使用 Apache 服务? 就像 John 所说的:限制是在使用 Web 服务的客户端上设置的。也许“您的服务行为”这句话有点误导。表述为“您的服务参考行为”是否更有意义? @john 它通过TcpClient 使用(该服务提供自定义二进制 blob,而不是 WCF/SOAP 或类似的)。如果您使用ServiceHost,而不是TcpClient,这些配置选项似乎会纯粹影响您;我错过了什么吗? 为什么不使用“添加服务参考”?【参考方案5】:

您是否尝试过以编程方式设置静态DefaultConnectionLimit 属性的值?

这里是关于真正令人头疼的信息的一个很好的来源...ASP.NET Thread Usage on IIS 7.5, IIS 7.0, and IIS 6.0,其中包含框架 4.0 的更新。

【讨论】:

我想这应该没关系,但我还是要试试。 这是我们几年前修复它的方法。我们遇到了并发问题,这似乎解决了问题。 Net.ServicePointManager.DefaultConnectionLimit = 1000 是我们使用的。您必须在创建连接类之前设置它。【参考方案6】:

如果它没有在托管 Web 服务消耗品的 Web 服务或应用程序或服务器(Apache 或 IIS)中定义,那么您可以创建无限连接直到失败

【讨论】:

【参考方案7】:

请参阅此页面的“线程”部分:http://msdn.microsoft.com/en-us/library/ff647786.aspx,以及“连接”部分。

您是否尝试过提高您的 processModel 设置的 maxconnection 属性?

【讨论】:

是的,我有。但是您引用的那篇文章指出了一些有趣的东西,而其他关于该主题的文章却忽略了提及:maxconnection 属性不适用于 local Web 服务调用。在这种特殊情况下,Web 服务 是本地的,但我们在服务不是本地的另一个环境中遇到了同样的问题。 @RobSobers - 我认为上面的链接值得一看。检查关于 minLocalRequestFreeThreads 的部分 - 如果可用线程的数量,此工作进程使用此设置将来自 localhost 的请求(其中 Web 应用程序调用同一服务器上的 Web 服务)排队在线程池中低于这个数字。此设置类似于 minFreeThreads,但它仅适用于使用 localhost 的请求 @Ahmad 是的,我也设置了minLocalRequestFreeThreads(请参阅问题中的machine.config

以上是关于是啥限制了我的 ASP.NET 应用程序可以与 Web 服务建立的同时连接数?的主要内容,如果未能解决你的问题,请参考以下文章

在 asp.net 中更推荐的 301 重定向方式是啥?

ASP NET 是啥?

Asp.net Core 中的内存使用限制

ASP.NET下实际使用的是啥版本的.NET框架

Windows 8.1 / Windows 10 破坏了我的 ASP.NET / IIS:“服务不可用”

ASP.NET - 阻止应用程序使用的最佳方法是啥?