私は wcf アプリケーションに取り組んでいますが、奇妙なタイムアウト動作が見られるようになりました。問題が wcf に関連しているかどうかを判断するために、実際のアプリケーションと同じ構成で foo アプリケーションを作成しました。
クライアント アプリケーション コードは次のとおりです。
public class Clients
{
public static void Main(string[] args)
{
var random = new Random();
var run = true;
var threads = 100;
for (int i = 0; i < threads; i++)
{
int delay = random.Next(1000, 1500);
var t = new Thread(() => {
var id = Guid.NewGuid().ToString("N").Substring(0, 10);
var client = new Client(@"client");
while (run)
{
Console.WriteLine(@"Sending thread id " + id);
client.Operation(@"Thread " + id);
Thread.Sleep(delay);
}
});
t.Start();
}
}
}
サーバー アプリケーション コードは、コンソールに送信されたデータのみをログに記録します。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.Single,
IncludeExceptionDetailInFaults = true,
UseSynchronizationContext = false,
ValidateMustUnderstand = false)]
public class Service : IService
{
public void Operation(string data)
{
Console.WriteLine(@"Data received: {0}", data);
}
}
これは app.config ファイルです。
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="Test.Service" behaviorConfiguration="throttle">
<endpoint name="service"
address="net.tcp://localhost/service"
binding="netTcpBinding"
bindingConfiguration="NetTcpBinding"
contract="Test.IService"/>
</service>
</services>
<client>
<endpoint name="client"
address="net.tcp://localhost/service"
binding="netTcpBinding"
bindingConfiguration="NetTcpBinding"
contract="Test.IService"/>
</client>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding"
portSharingEnabled="true"
closeTimeout="00:01:00"
openTimeout="00:00:30"
receiveTimeout="00:00:10"
sendTimeout="00:00:10"
transactionFlow="false"
transferMode="Streamed"
transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="6553600"
maxBufferSize="6553600"
maxConnections="500"
maxReceivedMessageSize="6553600">
<readerQuotas maxDepth="128"
maxStringContentLength="3276800"
maxArrayLength="6553600"
maxBytesPerRead="1638400"
maxNameTableCharCount="6553600"/>
<security mode="None">
<transport protectionLevel="None"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="throttle">
<serviceThrottling maxConcurrentCalls="1000"
maxConcurrentInstances="10"
maxConcurrentSessions="500"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
両方のアプリケーションを実行し、クライアント アプリケーションのスレッド数が 100 であれば、すべて問題ありません。しかし、スレッド数を 300 に変更すると、次の例外が発生します。
System.ServiceModel.CommunicationException: The socket connection was aborted.
This could be caused by an error processing your message or a receive timeout
being exceeded by the remote host, or an underlying network resource issue.
Local socket timeout was '00:00:10'.---> System.Net.Sockets.SocketException:
An existing connection was forcibly closed by the remote host at
System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32
offset, Int32 size, TimeSpan timeout, Boolean closing)
クアッドコア マシンでポート共有を使用しており、サービスは自己ホスト型です。
これは実際のアプリケーションと同じ問題ですが、タイムアウトが長くなります (2 分半)。InstanceContextMode.Single を使用したサービスが処理できる接続の最大数が 300 であるとは信じられません。デフォルトの ChannelInitializationTimeout 値 (5 に設定) に関する問題について読みましたが、それが問題だとは思いません (別のテストでは、すべてのスレッドに対して 1 つのクライアントを作成して開き、すべてを開始するまで 6 秒待ちました)。スレッド、結果は 10 秒後に同じ例外でした)。おそらく、私は間違った方法で何かを設定しています。
誰かが手がかりやアイデアを持っているなら、彼らは役に立ちます。前もって感謝します。
アップデート
バインディングを netTcp から basicHttpBinding に変更したところ、すべて正常に動作するようになりました (CommunicationExceptions はスローされません)。また、サービスで以前よりも速くメッセージを取得し始めましたが、basicHttpBinding でこの改善が得られた理由を知っている人はいますか?