关于wcf 的连接超时问题

今天网上的系统突然报错,经过排查是调用wcf报错了,报错信息如下:

System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:00. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The request operation did not complete within the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout.
   at System.ServiceModel.Channels.ReliableRequestSessionChannel.SyncRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   --- End of inner exception stack trace ---

网上找了半天资料,这篇帖子是很有价值的

I also had this timeout problem.  The client requests to my WCF service would work 3 to 6 times, then it would fail with a timeout.  I was passing tiny messages back and forth, so I knew "I cannot accomplish such big error with such tiny messages" ;-) 

The problem was I was forgetting to call .Close() on the WCF client object!  Once I added the appropriate ".Close()", the error disappeared. 

So once you're done calling the WCF service, make sure to call Close(), probably in your Finally block.


经过排查确实是相关的部门调了这个服务,没有加.Close().导致的.

在这个部门没有修改代码之前,服务器的配置如果需要修改,可以增加service的配置连接数

<serviceBehaviors>

<behavior name="ServiceBehavior">

<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->

<serviceMetadata httpGetEnabled="true"/>

<dataContractSerializer maxItemsInObjectGraph="10000000"/>

<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->

<serviceDebug includeExceptionDetailInFaults="true"/>

<serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="100" maxConcurrentInstances="100" />

</behavior>

</serviceBehaviors>


如果wcf是宿主在iis上的,可以增加iis的全局配置

http://www.cnblogs.com/z2002m/archive/2012/10/26/1918342.html

这篇很有价值了

IIS的MaxConnection的验证

最近公司有位仁兄写了一个监控IIS的软件,里面提到一个连接数, 此连接数主要是收集WMI信息, 

 

把代码写一下:

 

// 取到IIS的各个站点    

System.Management.ManagementClass mc = new System.Management.ManagementClass("Win32_PerfFormattedData_W3SVC_WebService");

 

// 每个站点 

  foreach (System.Management.ManagementObject obj in mc.GetInstances()) 

{

// 这里就是每个站点当前的连接数  

 Convert.ToInt64(obj.Properties["CurrentConnections"].Value);    // 

 

乍一看, 此 CurrentConnections是做什么用的呢? 由于我一直想了解一个IIS站点默认在同一时刻究竟能接受多少连接请求,  上网查了查,查到了maxconnection。 

 

首先看看微软是怎么解释的:

 

The maxconnection parameter determines how many connections can be made to a specific IP address.

这个 maxconnection参数用来确定: 对于每个IP能容纳多少个连接数(翻译的并不一定准)。   

  <connectionManagement>  

<add address="*" maxconnection="2"> // 这里就说明是2个

</connectionManagement>


这个 maxconnection会不会是并发连接数呢?   

 

我们来看看 http://www.microsofttranslator.com/BV.aspx?ref=CSSKB&from=en&to=zh-chs&a=http://support.microsoft.com/kb/821268/en-us?fr=1 

 

里面有一段写的很明白,  

 

  • maxWorkerThreads 参数和 maxIoThreads 参数的值设置为 100
  • maxconnection 参数的值设置 12 * N (其中,N 是您的 cpu 的数量)。
  • 设置要 minFreeThreads 参数的值 88 * N 和 minLocalRequestFreeThreads 参数,76 * N
  • minWorkerThreads 的值设置为 50请记住 minWorkerThreads 不是默认的配置文件中。您必须添加它。
这些建议的一些涉及一个简单的公式,涉及在服务器上的 cpu 数量。N 表示公式中的 cpu 数量的变量。这些的设置如果您有超线程启用,您必须使用逻辑 cpu 数而不是物理 cpu 数。例如如果启用超线程与四个处理器的服务器然后 N 公式中的值将是 8,而不是 4

请注意在使用此配置时您可以执行的每个 CPU 12 ASP.NET 请求最多在同一时间因为 100-88 = 12因此,至少 88 * N 工作线程和 88 * N 完成端口线程都可用的其它用途 (例如 Web 服务回调)。

 

基本上就明白了。  maxconnection = 12*CPU数量。   我们公司的服务器是使用双核的, 也就是说,在默认的情况下,

 

我们公司服务器上的IIS站点的默认最大连接数是24,  

 

接下来验证一下, 测试的目的是为了证明: 当超过24个访问连接候,IIS的站点还能不能接受其他的连接,   

 

实现准备:

1 写一个WEBService,里面包括A和B方法,其中A方法里面就一句Thread.Sleep(十分钟), 而B方法则直接Return "OK";  

2  VS2008负载测试(模拟24个用户同时访问一台服务器上的webServiceA方法,因为A方法是会让线程休眠十分钟)   

3  同时在服务器上收集WMI信息来观测WEBService当前的连接数, 使用: obj.Properties["CurrentConnections"].Value (具体收集方法看本文开头)

 

 

    这是负载测试, 

 

  这是负载测试调用的测试方法。

 

OK, 准备就绪, 开吃。。哦,不对, 开始测试,这里我就不贴出来当时测试的图,  我把我测试的结果告之一下, 

 

当负载测试开始,  Webservicer  的 obj.Properties["CurrentConnections"].Value 值,一直在增加, 当增加到24时,也就是我们模拟的24个用户,

 

我们在本机再模拟编写一段访问WebServiceB方法的代码,注意B方法是不会使线程休眠的,直接Return "ok" . 结果一直等到超时,也没有OK显示, 

 

但此时 obj.Properties["CurrentConnections"].Value的值为25,

 

如果我们把负载并发数的设为23呢,再启动负载测试, 当连接数达到23时, 再调用B方法,结果发现,大约在三秒钟,调用B方法成功了,显示“OK”,

 

 

顺便提一句:在ASP.NET 2.0中,引入了autoConfig属性:

1<processModel autoConfig="true"/>

当值为true时,autoConfig在运行时修改配置如下: 

 

  • 设置maxWorkerThreaders和maxIoThreads为100
  • 设置maxconnection 为12*CPU数量
  • 设置minFreeThreads为88*CPU数量
  • 设置minWorkerThreads为50

 

 

 


 

 

如果大家说, 我有一台猛机, 配置牛B, 这些默认的设置不够,我需要自已动用配置, OK, 可以直接在machine.config里修改, 

 

下面是示例代码, 

 <system.net>
   <connectionManagement>
      <add address = "*" maxconnection = "24" />
    </connectionManagement>
 </system.net>
  <system.web>
    <httpRuntime minFreeThreads="176"  minLocalRequestFreeThreads="152"/>
    <processModel autoConfig="false" maxWorkerThreads="100" maxIoThreads="100"/>

 

有些人会问: 这个东东一定要在 machine.config里修改吗? 能不能在web.config里面呢,目前我在Webserive程序里面的Web.config

修改了   <add address = "*" maxconnection = "30" />, 但使用负载测试时,发现还是不行,只能达到24, 这就说明30并未起作用。 

有知道的说明一下,为什么不行? 按照微软的说明,应该在web.config里面是可以起作用的,

 

需要注意的是: 如果增加了maxconnection 数量, maxWorkerThreads的数量也需要增加相当的数量, 比如在双核的CPU上, 修改maxconnection = 25,

 

则 maxWorkerThreads也需要修改为101, 因为 maxconnection = maxWorkerThreads --minFreeThreads  

 

 


 

 

还有一个疑问: 如果IIS崩溃了, 这里正好有一个HTTP请求过来,那么IIS会怎么处理?  答案中最好有微软的官方说明。  

 

 


 

 

结论: IIS的站点默认的并发连接数是12*CPU,也就是说默认设置下IIS在同一时刻能处理的最大请求数是12*CPU数量 。

 

欢迎猛烈拍砖,有什么好建议你老就使劲的提吧。谢谢你了。


©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页