我正在开发一个 wcf 应用程序,我开始看到一个奇怪的超时行为。我创建了一个与真实配置相同的 foo 应用程序,以确定问题是否与 wcf 相关。
客户端应用程序代码是这样的:
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 分半钟)。我不敢相信 300 是具有 InstanceContextMode.Single 的服务可以处理的最大连接数。我阅读了有关默认 ChannelInitializationTimeout 值(设置为 5)的问题,但我认为这不是问题(在另一个测试中,我开始为所有线程创建并打开一个客户端,并等待 6 秒以启动所有线程)线程,结果是 10 秒后的相同异常)。也许我正在以错误的方式配置某些东西。
如果有人有线索或想法,他们会有所帮助。提前致谢。
更新
我将绑定从 netTcp 更改为 basicHttpBinding,现在一切正常(没有引发 CommunicationExceptions)。此外,我开始比以前更快地在服务中获取消息,有谁知道为什么我会通过 basicHttpBinding 获得这种改进?