2

我们有一个服务器从 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。

4

3 回答 3

1

听起来您在应用程序的某个地方正在使用非异步 IO,您在其中阻塞了操作的结果。您可能在许多地方使用了适当的异步,例如从服务器与客户端的主要连接,但在连接到数据库或类似的东西时,您可能没有使用。异步和非异步的这种混合可能是您创建如此多线程的原因。

通过确保您没有阻塞 IO,它应该确保您没有很多线程池线程无所事事,这似乎是您所处的情况。

于 2013-06-06T15:08:29.723 回答
0

我从来没有同时处理过这么多的请求,但是您可以尝试创建与 cpu 上的内核一样多的线程,然后实现排队系统。您的线程将一次消耗队列一个设备的坐标。这样我猜你的CPU会全速使用......

于 2013-06-06T14:57:35.173 回答
0

你在服务器上做什么样的操作?

如果它们受CPU 限制,那么拥有比内核更多的线程是没有用的,并且添加更多可能会使您的服务器混乱,因为一堆线程像狗一样战斗;)

在这种情况下,您应该更幸运地使用简单的处理循环,每个核心一个。

于 2013-06-06T14:35:36.307 回答