对于帖子长度,我表示歉意,但有很多事情可能会导致我的情况,并且我试图根据其他帖子包含所做的所有设置更改。简而言之,我的WCF服务似乎一次只限制3个或4个并发客户端请求。如果我将应用程序池Maximum Worker Processes设置得更高(大约10)或将服务行为ConcurrencyMode设置为Multiple,则我可以获得更好的吞吐量(几倍更快)。然而,这些看起来像解决真正的问题,带来他们自己的问题。我误解了,还是应该IIS能够在一个工作进程中调用我的WCF服务的许多实例(数十个或更多)来处理负载?我只知道我错过了某个地方的设置,但我找不到它。WCF吞吐量低于预期
编辑:在试验到目前为止的建议,我意识到我的数学是关闭吞吐量。使用ForEach循环,我可以在低20s(每个任务持续时间*任务数/总运行时间)的服务器上获得预计的并发处理。对于正在进行的实际工作(睡眠10秒),这似乎仍然很低,但不再低得可笑。
第二编辑:我标记@Pablo的评论是答案,因为他的回答加上他的链接给了我显着提升表现的信息(我想大约3倍)。但是,我想提出后续问题 - 在WCF/IIS中处理并发请求的合理期望是什么?假设CPU,内存和IO不是瓶颈,处理请求的实际限制/期望值(每个CPU)是多少?我正在寻找的是一个经验法则,告诉我如果不添加CPU(或工作进程),我可能不会获得更大的提升。再次感谢。
(在Windows 2008 Server,通过IIS,1个处理器托管)
WCF服务配置(略):
<?xml version="1.0"?>
<configuration>
<configSections>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<services>
<service name="FMHIRWCFSvc.IRService" behaviorConfiguration="IRServiceBehavior">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="Binding1" contract="FMHIRWCFSvc.IIRService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="Binding1" maxReceivedMessageSize="104857600">
<readerQuotas maxArrayLength="104857600"/>
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="IRServiceBehavior">
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceThrottling
maxConcurrentCalls = "500"
maxConcurrentSessions = "500"
maxConcurrentInstances = "500"
/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<applicationSettings>
<FMHIRWCFSvc.Properties.Settings>
<setting name="FMHIRWCFSvc_ir_dev_websvc_IRWebService40" serializeAs="String">
<value>http://ir-dev-websvc/imageright.webservice/IRWebService40.asmx</value>
</setting>
</FMHIRWCFSvc.Properties.Settings>
</applicationSettings>
<system.net>
<connectionManagement>
<add address="*" maxconnection="500"/>
</connectionManagement>
</system.net>
</configuration>
客户端配置(略):
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IIRService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://{myserveraddress}/FMHIRWCFSvc/IRService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IIRService"
contract="wcf_local.IIRService" name="BasicHttpBinding_IIRService" />
</client>
</system.serviceModel>
<system.net>
<connectionManagement>
<add address="*" maxconnection="500"/>
</connectionManagement>
</system.net>
</configuration>
客户端方法调用:
static void WCFTesting()
{
ConcurrentQueue<Exception> exceptionList = new ConcurrentQueue<Exception>();
int[] taskList = new int[250];
Parallel.ForEach(taskList, theTask =>
{
try
{
// Create the WCF client
BasicHttpBinding binding = new BasicHttpBinding {
Security = { Mode = BasicHttpSecurityMode.Transport },
SendTimeout = TimeSpan.FromSeconds(20)
};
EndpointAddress endpointAddress = new EndpointAddress("https://{myserveraddress}/FMHIRWCFSvc/IRService.svc");
IRServiceClient wcfClient = new IRServiceClient(binding, endpointAddress);
// Call wcf service method that sleeps 10 seconds and returns
wcfClient.TestCall();
}
catch (Exception exception) {
// Store off exceptions for later processing
exceptionList.Enqueue(exception);
}
});
}
WCF服务代码:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
...
public string TestCall()
{
Thread.Sleep(10000);
return null;
}
感谢您的任何见解或建议!
感谢您的帮助。当我使用手动线程创建代码时,我确实得到了并发的提升(估计低30s而不是20s),但不是我希望的跳跃,就像允许许多IIS工作进程(web garden)一样。我的想法是,如果增加员工流程的数量会大大提高绩效,那么客户并不是瓶颈。如果服务器硬件不征税(CPU使用率低,内存使用率低,I/O活动低),还有什么可能会限制吞吐量?我真的是最大化WCF服务,我的下一步是更多的工作流程? – 2012-07-13 16:34:09
我认为一个问题可能与WCF和IIS如何处理ThreadPool有关。长时间运行的请求(特别是在突发期间)存在固有的问题,因为池中的线程数量非常少。有一个彻底的帖子[这里](http://www.codeproject.com/Articles/234085/Fixing-WCF-to-build-highly-scalable-async-REST-API)分析WCF的线程行为,一些建议,作为以及来自Microsoft的其他建议:http://support.microsoft.com/kb/2538826,http://blogs.microsoft.co.il/blogs/idof/archive/2011/05/05/problems-with-wcf -scaling.aspx – 2012-07-13 20:51:02
感谢您的链接。我没有阅读(并理解)所有的链接,但是我可以通过IOCP线程创建解决方法链接将性能提高一倍。这使我用我的测试方法平均处理了78个并发处理的请求。我现实世界的场景同时在35个左右。我想我已经耗尽了所有实用的编程解决方案,需要更多地关注服务器管理解决方案。 – 2012-07-16 21:03:09