我们有一个从500-1500个GPS设备接收数据的服务器。每个设备每10-30秒发送一个包含大约1-4个GPS坐标的数据包。服务器是异步设计的,侦听器使用Begin- EndAccept处理连接,使用Begin- EndReceive处理通信。一旦接收到分组,数据就被处理并存储在数据库中。
对于很少的设备(500-700个设备),这只需要50ms,并且我们只有不到50个并发线程在运行,实际的CPU使用率(20-40%)。然而,当服务器承受着连接(1000+)的压力时,线程的数量会激增到500-600,CPU使用率也会下降到几个百分点。处理时间也增加到几分钟。
对于以这种速率发送许多小数据包的特定场景,异步设计是不是很糟糕,还是代码中存在问题?
我们目前不得不将负载分布在三台服务器上以容纳所有设备,它们都是托管在Hyper-V服务器上的具有6个CPU和4 4GB内存的虚拟机。
解决方案:
我从人们的回答中找到的解决方案是,立即使用.Net并行库将其调度为任务,因为当跨多个内核调度线程时,这种方法要智能得多:
void EndReceive(IAsyncResult res)
{
Task.Factory.StartNew((object o) => { HandleReceive(o as IAsyncResult); }, res, TaskCreationOptions.PreferFairness);
}现在线程数很少超过50个。
发布于 2013-06-06 23:08:30
这听起来像是在应用程序中的某个地方使用了非异步IO,在这种IO中,您阻塞了操作的结果。您可能在许多地方使用了适当的异步,例如从服务器到客户端的主连接,但当连接到数据库或类似的东西时,您可能没有这样做。异步和非异步的混合很可能是创建了这么多线程的原因。
通过确保您没有阻塞IO,它应该确保您不会有大量线程池线程无所事事,这似乎就是您所处的情况。
发布于 2013-06-06 22:35:36
你在服务器上做什么操作?
如果它们是占用CPU的,那么线程比内核多是没有用的,添加更多的线程可能会使您的服务器变得混乱,一堆线程像狗一样打架;)
在这种情况下,您应该更幸运地使用简单的处理循环,每个核心一个。
发布于 2013-06-06 22:57:35
我从未同时处理过如此多的请求,但您可以尝试创建与cpu上的内核一样多的线程,然后实现一个排队系统。您的线程将一次占用一个设备的坐标来完成队列。通过这种方式,我猜你的CPU将会全速使用……
https://stackoverflow.com/questions/16964712
复制相似问题