2012-06-27 69 views
9

我正在进行性能测试,涉及多个客户端,每个客户端以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%浪费在“等待同步

当我打开调用图我觉得这看起来很奇怪两个东西,但我不知道他们的意思:

  1. 在树的顶部正在使用System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke,是OK用于并发处理?
  2. 所有同步问题涉及某种形式的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); 
     } 
+0

你正在使用什么类型的实例和协议模式? –

+0

它看起来像我没有设置任何模式,所以默认设置适用...我记得我想添加每会话/多个,但可能错过了它,我应该添加它? – Mithir

+4

persession/single默认情况下,尝试使用多种协议模式 –

回答

4

PerCall在这些情况下你可能会考虑这种实例化模式。

  • 如果你的服务是无状态的

  • 如果您的服务具有重量轻初始化代码(或根本没有
    全部)。

  • 如果您的服务是单线程的。

一些很好的教程。查看关于调整的第三个链接。

WCF Instancing, Concurrency, and Throttling – Part 1

WCF Instancing, Concurrency, and Throttling – Part 2

WCF Instancing, Concurrency, and Throttling – Part 3

+0

感谢您的建议,我已经尝试了两个,但仍然请求排队等待发送到数据库服务 – Mithir

+0

只是伸手可能看看你如何正在激活客户端进行测试。你可能会在同一张桌子上独占锁吗? – Paparazzi

+0

该问题不会发生在实际的数据库上,而是发生在激活数据库的服务上。在表格甚至出现问题之前,请求在进入该服务之前排队。 – Mithir

2

会每次通话喜欢。如果要最小化初始化资源密集型对象或为每个请求运行某些预处理路由或希望维护状态,那么会话将非常有用。会话可以给你更好的表现,但每次通话总是更好。在每次通话中,您不必担心通话情况。而persession/multiple的缺点是你必须总是考虑代码中的线程安全性。

+0

我真的不知道发生了什么......我在所有服务上都将它设置为PerCall或PerSession多个,但它似乎并不重要,主要的http wcf服务打开了很多线程,但只有少数几个转到DB连接服务... – Mithir

+0

它是否存在concureent请求的问题,或者它通过打开多个实例来减慢doen? –

+0

我已经添加了WCF服务的一些配置文件,希望它有一点帮助 – Mithir

1

最好的办法是每次通话,如果你不关心服务的状态,如果没有重型起重是在初始化的时候,我认为你的描述的情况下。尝试并移除这些DAL电话并查看您的服务的行为方式,这样您就能够确定这是否是您的瓶颈。

+0

这实际上与您正在帮助的其他问题有关,谢谢! :) – Mithir

+0

我已经在问题中添加了一些配置文件。操作系统是Windows Server 2008。 – Mithir

相关问题