今天网上的系统突然报错,经过排查是调用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会不会是并发连接数呢?
里面有一段写的很明白,
- 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数量 。
欢迎猛烈拍砖,有什么好建议你老就使劲的提吧。谢谢你了。