我们有一个服务器从 500-1500 个 GPS 设备接收数据。每个设备每 10-30 秒发送一个包含大约 1-4 个 GPS 坐标的数据包。服务器是异步设计的,侦听器使用 Begin-EndAccept 处理连接,并使用 Begin-EndReceive 进行通信。一旦接收到数据包,数据就会被处理并存储在数据库中。
对于很少的设备(500-700 台设备),这仅需要 50 毫秒,并且我们运行的并发线程少于 50 个,并且 CPU 使用率是真实的(20-40%)。但是,当服务器受到连接(1000+)的压力时,线程数会激增至 500-600,并且 CPU 使用率也会下降到百分之几。处理时间也增加到几分钟。
异步设计对于这种特殊情况是否不利,许多小数据包以这种速率发送,或者可能是代码中的问题?
我们目前不得不将负载分布在三台服务器上以容纳所有设备,它们都是托管在 Hyper-V 服务器上的具有 6 个 CPU 和 4GB 内存的 VM。
解决方案:
我从人们的回答中找到的解决方案是立即将其安排为使用 .Net 并行库的任务,因为这在跨多个内核调度线程时要聪明得多:
void EndReceive(IAsyncResult res)
{
Task.Factory.StartNew((object o) => { HandleReceive(o as IAsyncResult); }, res, TaskCreationOptions.PreferFairness);
}
现在线程很少超过 50。