2012-06-27 68 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

相關問題