WCFの接続制限に関する設定を調査してみた
作成したアプリケーションのパフォーマンスに問題があって、WCFの接続制限になにがあるのか調査してみた。
WCFのプロセスモデル
WCFサービスを作成するときは、アクティブ化と同時実行のモデルを決める必要があります。このモデルは ServiceBehavior属性のInstanceContextModeとConcurrencyModeで制御します。
ConcurrencyModeをSingleまたはReentrantに設定するときは、InstanceContextModeをSingleに設定しないようにします。ConcurrencyModeをMultipleにし、粒度の細かいロックを使用すると同時実行のパフォーマンスが向上します。
InstanceContextMode | 意味 |
---|---|
PerCall | 呼び出すたびにサービスオブジェクトのインスタンスを作成する。 |
PerSession(規定値) | セッションごとにサービスオブジェクトのインスタンスを作成する。チャンネルが複数のセッションをサポートしなければPerCallと同じ。 |
Single | すべての呼び出しに一つのサービスオブジェクトのインスタンスを再利用する。 |
ConcurrencyMode | 意味 |
---|---|
Single(規定値) | サービスオブジェクトはシングルスレッド処理になり、再入可能はサポートしない。新たな要求は待機状態になる。 |
Reentrant | サービスオブジェクトはシングルスレッド処理になるが、再入可能。再入が行われるので、別のサービスを呼び出す前にオブジェクトを一貫した状態に保つ必要がある。 |
Multiple | 同期は保証されないため、サービスは独自に同期を処理し、状態の一貫性を確保する必要がある。 |
OperationBehavior.ReleaseInstanceModeにReleaseInstanceMode.None以外の値を設定することで、インスタンスの生存期間をコントロールできます。ServiceBehavior.ContextModeがPerSessionのときに組み合わせて使用すると効果があります。
ReleaseInstanceMode | 意味 |
---|---|
AfterCall | サービスメソッド呼び出し後にインスタンスを破棄する。 |
BeforeCall | サービスメソッド呼び出し前に既存のインスタンスを破棄し、新しいインスタンスを作成する。 |
BeforeAndAfterCall | サービスメソッド呼び出し前に新しいインスタンスを作成し、呼び出し後にインスタンスを破棄する。 |
None(規定値) | インスタンスの破棄はServiceBehavior.InstanceContextModeにより決定される。 |
WCFの接続制限に関する設定
ServiceThrottlingには同時実行の制限があります。
-
maxConcurrentSessions : 同時に処理されるメッセージ数。
制限数を超える呼出しはキューに登録される。
規定値は.NET 3.5では10、.NET 4では論理プロセッサ数の100倍。 -
maxConcurrentCalls : 同時に実行されるInstanceContextオブジェクト数。
制限数を超えるインスタンス作成要求はキューに登録され、制限数を下回りスロットが利用可能になると作成が完了する。
規定値は.NET 3.5では16、.NET 4では論理プロセッサ数の16倍。 -
maxConcurrentInstances : オブジェクトが許容できるセッション数。
制限数を超える接続を受け入れるが、制限数以下のチャネルしかアクティブにならない。
規定値は.NET 3.5では26、.NET 4では論理プロセッサ数の116倍。
<configuration>
<system.serviceModel>
<behaviors>
<serviceThrottling>
<serviceThrottling
maxConcurrentCalls="16"
maxConcurrentSessions="10"
maxConcurrentInstances="26"
/>
</serviceThrottling>
</behaviors>
</system.serviceModel>
</configuration>
TCPレベルの接続制限
アプリケーションがホストごとに許可される同時接続数の規定値は2つです。
外部WCFサービスを呼び出す場合に、この制限がボトルネックになります。
他にもOSの接続制限があります。
<configuration>
<system.net>
<connectionManagement>
<add address = "*" maxconnection = "2" />
</connectionManagement>
</system.net>
</configuration>
スレッドプールの制限
WCFはスレッドプールのI/O完了スレッドからサービスオブジェクトを呼出します。
ASP.NETではsystem.Webセクションを編集します。デスクトップアプリではThreadPool.SetMinThreadsとThreadPool.SetMaxThreadsを呼び出します。
規定値は、Minの方のスレッドプール数が4、非同期I/Oが4で、Maxの方のスレッドプール数が1023、非同期I/Oが1000です。
<system.Web>
<processModel
maxWorkerThreads="num"
maxIoThreads="num"
minWorkerThreads="num"
minIoThreads="num"
/>
</system.Web>
ThreadPool.SetMinThreads(ワーカスレッドの下限, 非同期I/Oスレッドの下限);
ThreadPool.SetMaxThreads(ワーカスレッドの上限, 非同期I/Oスレッドの上限);
参考
https://www.amazon.co.jp/dp/4798131792
http://www.pine4.net/Memo/Article/Archives/17