我正在进行性能测试,涉及多个客户端,每个客户端以150个请求的速度轰击服务器,尽可能快地进行。为什么我的应用程序等待同步这么多?
服务器从3个WCF服务构成,一个被打开以外侧httpbinding,它经由net.pipe(IPC)会谈到其它2个服务。其中一个服务负责数据库连接(SQL Server 2008 R2)。
该DB连接服务使用下面的连接字符串enhancments:
Min Pool Size=20; Max Pool Size=1000; Connection Timeout=20;
是WCF节流(像所有其他的WCF服务)。
我注意到,当我激活1个客户可能需要3秒,但是当我启动3个客户可能需要8-9以上。
我与SQL Server事件探查器检查,看看有多少并发进程使用,我看到正在使用的只有约8进程。
所以我意识到在服务器的某个地方,请求会被排队而不是被同时处理。
为了得到我已经使用了性能剖析它的底部(蚂蚁准确),这表明我的时间约70%浪费在“等待同步
当我打开调用图我觉得这看起来很奇怪两个东西,但我不知道他们的意思:
- 在树的顶部正在使用System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke,是OK用于并发处理?
- 所有同步问题涉及某种形式的SQL Server活动,喜欢的ExecuteNonQuery,的ExecuteReader等(当我到调用树的底部)
我注意到,DB连接服务使用DAL项目(一些遗留代码,遗憾的是)这完全是静态的。
阅读this后,我不知道如果DAL的代码是有问题的或不是,这里是一个存储过程调用的一个样本。
这种方法usualy从DB连接服务名为:
public static int PerformStoredProcedureWithParams(string storedP,string ext,out string msg, params object[] pars)
{
msg = "";
SqlCommand command = GetSqlCommand(storedP,ext);
UpdateCommandParams(command, pars);
command.Connection.Open();
int result = (int)PerformStoredProcedure(command,out msg);
command.Connection.Close();
return result;
}
那么,有什么不对吗?
或者我应该去别的地方看看?
编辑:
Brijesh的评论后,我意识到我没有改变的WCF服务的默认InstanceContextMode和ConcurrencyMode ...初学者的错误的种类我猜。
我还不能肯定,如果我要使用PerSession /多或PerCall /单。正如我所看到的,每个服务都应该按照对象处理每个请求,而不管客户端。
我应该使用什么?
2日编辑:
使用PerCall和PerSession /多后,我注意到,仍然有(至少在DB服务)没有变化。我所看到的是,主入口点服务可能会打开大量线程,但在数据库连接服务中只能打开几个(大约8-10个线程)。
有什么其他的原因,为什么会发生这种情况?我排除了DAL是一个问题,因为没有足够的请求在DB服务去让我的身影了其在服务或东西在客户端的东西...
3日编辑:
下面是配置文件:
管理器的配置WCF服务部分:
<services>
<service behaviorConfiguration="ServicesBehavior" name="Verifone.GenericPP.GPPManagerService.GPPManagerServiceImpl">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9090/GPPManagerService/"/>
</baseAddresses>
</host>
<endpoint contract="Verifone.GenericPP.GPPManagerService.IGPPManagerService" binding="basicHttpBinding" address="GPPManagerService"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServicesBehavior">
<!--amith 13-05-2012-->
<serviceThrottling
maxConcurrentCalls="1000"
maxConcurrentSessions="1000"
maxConcurrentInstances="1000"
/>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding" maxBufferSize="10000000" maxReceivedMessageSize="10000000">
<readerQuotas maxStringContentLength="10000000" maxArrayLength="10000000"/>
<security mode="None">
<transport clientCredentialType="None"/>
</security>
</binding>
经理的客户:
<endpoint name="endpoint1" contract="IDBConnectionContract" bindingConfiguration="basicHttpBinding" binding="basicHttpBinding" address="http://localhost:9010/DBConnectionService/DBService"></endpoint>
<endpoint name="endpoint2" contract="IGPPService" bindingConfiguration="basicHttpBinding" binding="basicHttpBinding" address="http://localhost:9095/GenericPPService/GenericPPService"></endpoint>
DB连接服务:
<service behaviorConfiguration="ServicesBehavior" name="Verifone.DBConnectionService.DBConnectionContracImpl">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9010/DBConnectionService/"/>
<add baseAddress="net.pipe://localhost/DBConnectionService/"/>
</baseAddresses>
</host>
<endpoint contract="Verifone.DBConnectionService.IDBConnectionContract" binding="basicHttpBinding" address="DBService"></endpoint>
<endpoint contract="Verifone.DBConnectionService.IDBConnectionContract" binding="netNamedPipeBinding" bindingConfiguration="NetNamedPipeBinding_Configuration" address="" name="pipeEndpoint"/>
</service>
商业逻辑服务的客户是非常像经理一样。
所有服务是自主办,我在经理的一个DBConnectionProxy类和业务代码,它们激活这样的:
DBConnectionContractClient _dbConnectionContractClient = null;
try
{
objDBConnectionContractClient = new DBConnectionContractClient();
objDBConnectionContractClient.ExecuteStoredProcedure(input, out result);
}
你正在使用什么类型的实例和协议模式? –
它看起来像我没有设置任何模式,所以默认设置适用...我记得我想添加每会话/多个,但可能错过了它,我应该添加它? – Mithir
persession/single默认情况下,尝试使用多种协议模式 –