如何扩展UDP读取吞吐量?

时间:2011-09-30 20:45:33

标签: linux

设置:两个linux(CentOS 6)服务器通过专用的GigE链路背对背连接。每个服务器有24个内核和32GB RAM

客户端:模拟器在一个线程中尽可能快地拍摄UDP数据包。每个数据包大小为256个字节。我看到最大吞吐量是~200,000包/秒。

服务器:在一个线程中接收UDP套接字上的数据包并执行轻量级解析。我看到最大吞吐量是~200,000包/秒,CPU 1个核心在处理过程中利用率为85%左右。没有数据包丢失,接收缓冲区设置为128M以防万一。

现在我想要使用另外23个内核,但是只要在服务器端添加一个线程来接收数据,并且在客户端通过专用套接字发送数据的客户端线程,我就会看到服务器端丢包很多。

服务器线程完全相互独立,除了I / O外不会阻塞。它们不会在套接字上竞争,因为它们中的每一个都从它们自己的UDP套接字中吸取数据包。

我看到以下行为:

  1. 每个核心的CPU大约为85%,如果是额外的核心,则使用大约90%的ksoftirqd / xx进程。
  2. 我正在丢失数据包,每个线程都会下降到大约120,000个数据包/秒
  3. Google表示ksoftirqd使用CPU来处理软中断,而重度系统调用(UDP读取)可能是此内核线程CPU使用率过高的原因之一。

    我通过将我的进程固定到同一个物理插槽上的一堆核心来重复实验,我发现性能提高到150,000个数据包/秒,但仍有一些相当大的数据包丢失。

    有没有办法可以提高程序的可扩展性并最大限度地减少数据包丢失?

3 个答案:

答案 0 :(得分:5)

首先,每秒200,000个数据包,每个数据包有256个(数据?)字节,一旦考虑到UDP,IP和以太网开销,您的千兆链路的运行容量几乎只有计算带宽的一半。 。在您推动的每秒数据包速率下,许多交换机(例如)会倒下。

其次,你可能被IRQ杀死了。更好的网卡具有可调参数,可以让您减少更少的IRQ以增加延迟(它们每N个数据包仅中断一次)。确保已启用该功能。 (要检查的地方是以太网卡的模块参数。)

答案 1 :(得分:0)

您可以设置内核接收缓冲区,但请注意,如果IRQ占用了所有CPU,它将无济于事。

int n = 1024 * 512; //experiment with it
if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1) {
  //oops... check this
}

您还应该将最大接收缓冲区设置为较大的值,以便内核不会限制您的设置:

sysctl -w net.core.rmem_max=<value>

答案 2 :(得分:-1)

如果您的应用程序每秒需要200,000个数据包,那么您的协议设计不合理,或者您正在做其他错误。

200k数据包来自哪里?互联网上的不同主机?也许你应该对它进行负载均衡?

正如derobert指出的那样,每秒200k数据包代表了很多带宽,这在互联网上代价很高,你应该考虑重新设计协议。