【发布时间】:2015-08-27 07:50:03
【问题描述】:
我正在使用 nettcpbinding 处理托管在 Windows 服务中的 WCF 服务。
当我尝试对服务执行负载测试时,我构建了一个简单的客户端,它在第二个调用大约 1000 次调用服务,从服务返回首先需要大约 2 到 8 秒,然后让简单客户端运行大约返回结果的时间增加了半小时,并且一些客户端对配置为 2 分钟的发送时间给出了一些超时异常。
我修改了服务限制配置,是这样的
这些是我尝试执行的步骤:
-
修改了服务节流配置
<serviceThrottling maxConcurrentCalls="2147483647" maxConcurrentInstances="2147483647" maxConcurrentSessions="2147483647"/> - 在 Windows 7 机器上工作,所以我搬到了服务器 2008,但结果相同。
-
更新 tcp binding 的配置如下 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"); } -
将我的服务功能更改为使用异步和等待
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; }并更新客户端以使用 async 并在它对服务的调用中等待。
- 应用了此链接中提出的 Worker 线程解决方案 https://support.microsoft.com/en-us/kb/2538826 虽然我使用的是 .net 4.5.1,并将 MinThreads 设置为 1000 worker 和 1000 IOCP
毕竟服务开始处理更多请求,但延迟仍然存在,简单的客户端需要大约 4 个小时才能超时
奇怪的是,我发现服务在 100 毫秒内处理了大约 8 到 16 次调用,这与服务中当前存在的线程数有关。
我发现很多文章都在谈论需要放在 machine.config 和 Aspnet.config 中的配置,我认为这与我的情况无关,因为我在 Windows 服务而不是 IIS 上使用 nettcp,但我已经实现了这些更改,发现结果没有变化。
有人可以指出我缺少什么或我想从服务中获得它无法支持的东西吗?
【问题讨论】:
-
如果方法不能在 1/1000 秒内运行,您将永远无法防止超时。你不断地提供服务数据,它处理它的速度不能比你提供它的速度快。最终漏斗会被填满,剩下的会失败。
-
如果您需要每秒处理 1000 个请求,您可能需要开始研究负载平衡/负载共享系统。
-
是的,他需要像 azure 这样有很多节点的东西。他需要一个可以连接到数据库、进行插入、查询数据、构建对象并在 1/1000 秒或更短的时间内将所有这些内容返回给用户的设置,以免超时断开连接。我在这里有杀手级 SQL 服务器平衡,我不能超过 4 毫秒,他需要快 4 倍。
-
@Franck,我很欣赏你的回答,但可以将我推荐给 MSDN 上的链接,以确保我是否走错路
-
请用客户端实现更新您的问题 - 可能是创建客户端实例需要很长时间,也可能是其他问题。您的 WS 方法实现是否执行任何长时间运行的计算或任何 IO 任务?可能问题不在 WCF 中,而是在等待数据库完成操作。
标签: c# wcf async-await threadpool nettcpbinding