我正在使用nettcpbinding处理在Windows服务中托管的WCF服务。
当我尝试对服务执行负载测试时,我构建了一个简单的客户端,该服务器在第二次调用服务大约1000次,从服务返回大约需要2到8秒,并且在离开简单客户端后运行大约半小时返回结果的时间增加了,有些客户端为发送时间提供了一些超时时间,配置为2分钟。
我修改了服务提升配置,就像这样
这些是我尝试执行的步骤:
修改了服务限制配置
<serviceThrottling maxConcurrentCalls="2147483647" maxConcurrentInstances="2147483647" maxConcurrentSessions="2147483647"/>
更新tcp绑定的配置如下所示 NetTcpBinding baseBinding = new NetTcpBinding(SecurityMode.None,true); baseBinding.MaxBufferSize = int.MaxValue;
baseBinding.MaxConnections = int.MaxValue;
baseBinding.ListenBacklog = int.MaxValue;
baseBinding.MaxBufferPoolSize = long.MaxValue;
baseBinding.TransferMode = TransferMode.Buffered;
baseBinding.MaxReceivedMessageSize = int.MaxValue;
baseBinding.PortSharingEnabled = true;
baseBinding.ReaderQuotas.MaxDepth = int.MaxValue;
baseBinding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
baseBinding.ReaderQuotas.MaxArrayLength = int.MaxValue;
baseBinding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
baseBinding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
baseBinding.ReliableSession.Enabled = true;
baseBinding.ReliableSession.Ordered = true;
baseBinding.ReliableSession.InactivityTimeout = new TimeSpan(23, 23, 59, 59);
BindingElementCollection elements = baseBinding.CreateBindingElements();
ReliableSessionBindingElement reliableSessionElement = elements.Find<ReliableSessionBindingElement>();
if (reliableSessionElement != null)
{
reliableSessionElement.MaxPendingChannels = 128;
TcpTransportBindingElement transport = elements.Find<TcpTransportBindingElement>();
transport.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint = 1000;
CustomBinding newBinding = new CustomBinding(elements);
newBinding.CloseTimeout = new TimeSpan(0,20,9);
newBinding.OpenTimeout = new TimeSpan(0,25,0);
newBinding.ReceiveTimeout = new TimeSpan(23,23,59,59);
newBinding.SendTimeout = new TimeSpan(0,20,0);
newBinding.Name = "netTcpServiceBinding";
return newBinding;
}
else
{
throw new Exception("the base binding does not " +
"have ReliableSessionBindingElement");
}
将我的服务功能更改为使用async并等待
public async Task<ReturnObj> Connect(ClientInfo clientInfo)
{
var task = Task.Factory.StartNew(() =>
{
// do the needed work
// insert into database
// query some table to return information to client
});
var res = await task;
return res;
}
并更新客户端以使用异步并等待它对服务的调用。
毕竟这项服务开始处理更多的请求,但延迟仍然存在,而简单的客户需要大约4个小时才能给出时间
奇怪的是,我发现该服务在100毫秒内处理大约8到16个呼叫,关于当前服务中存在的线程数。
我发现很多文章谈论需要放在machine.config和Aspnet.config中的配置,我认为这与我的情况无关,因为我在Windows服务上使用nettcp而不是IIS,但我实现了这些变化,发现结果没有变化。
有人可以指出我所缺少的东西,或者我想从服务中得到它无法支持的东西吗?
答案 0 :(得分:1)
可能是您的测试客户端的编写方式。使用NetTcp,当您创建通道时,它会尝试从空闲连接池中获取一个通道。如果它为空,则会打开一个新的套接字连接。当您关闭客户端通道时,它将返回到空闲连接池。空闲连接池的默认大小为10,这意味着一旦空闲池中有10个连接,任何后续关闭将实际关闭TCP套接字。如果您的测试代码正在快速创建和处理通道,则可能会丢弃池中的连接。然后,您可能会在TIME_WAIT状态下遇到太多套接字的问题 Here是一篇描述如何修改池行为的博客文章。
答案 1 :(得分:0)
这很可能是由于并发模式设置为Single(这是默认值)。尝试通过将ServiceBehaviourAttribute添加到服务实现来将ConcurrencyMode设置为Multiple。
请务必查看文件:https://msdn.microsoft.com/en-us/library/system.servicemodel.concurrencymode(v=vs.110).aspx
示例:
// With ConcurrencyMode.Multiple, threads can call an operation at any time.
// It is your responsibility to guard your state with locks. If
// you always guarantee you leave state consistent when you leave
// the lock, you can assume it is valid when you enter the lock.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
class MultipleCachingHttpFetcher : IContract
您可能也对描述并发问题的Sessions, Instancing, and Concurrency文章感兴趣。