我正在進行性能測試,涉及多個客戶端,每個客戶端以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默認情況下,嘗試使用多種協議模式 –