gpt4 book ai didi

linux - Linux 上的 UDP 服务器应用无法接收来自超过 150 个客户端的数据包

转载 作者:太空狗 更新时间:2023-10-29 12:19:39 27 4
gpt4 key购买 nike

我已经在 Linux 上编写了一个 UDP C++ 服务器应用程序,现在正在对其进行负载测试以查看它可以处理多少客户端。我发现它在大约 150 个并发客户端以每秒 2-4 个的速率发送数据包时达到峰值。

在此之后添加的客户端会导致一些其他客户端的数据包被丢弃。

服务器本身没有压力,使用不到 10% 的 CPU 和内存。网络也完全没有压力,大约 15K 字节/秒。数据包以大约 200 个数据包/秒的速度到达服务器(它使用一个 UDP 套接字进行读取和写入)。在此负载级别,服务器线程本身仍会短时间休眠。

问题:
关于这里的瓶颈是什么的任何想法? CPU、网络和服务器代码本身似乎都没有压力。操作系统是否无法处理这个数量的 UDP 数据包?

硬件功耗非常低 - 相当于 1.5 MHz 的单核奔腾处理器。 NIC是100M位/秒。我正在运行 Ubuntu 11.1。

这篇文章可能是相关的:Upper limit to UDP performance on windows server 2008

更新:服务器设置一个 UDP 套接字,然后创建 3 个线程和 2 个队列。第一个线程阻塞套接字读取,看起来像:

while (1)
{
recvfrom(this->socket, readBuf, BUFSIZE, 0, (sockaddr *)&address, &addressLen);
pushBack(this->inputQueue, message);
}

第二个线程在 inputQueue 上休眠。当发出条件信号并处理消息时,它会唤醒。它将处理过的消息发送到输出队列:

while (1)
{
sleepOnQ(this->inputQueue);
popFront(this->inputQueue);
processMessage();
pushBack(this->outputQueue, message);
}

第三个线程在 outputQueue 上休眠,并将消息从 UDP 套接字发送到目的地。请注意,它与用于读取的套接字相同。

while (1)
{
sleepOnQ(this->outputQueue);
popFront(this->outputQueue);
processMessage();
sendto(this->socket, message, ... );
}

每个客户端和消息的处理量很小。正如我提到的,当服务器每秒处理 200 条消息时,它使用了大约 10% 的 CPU。

以下是系统上的一些内核参数:

net.core.wmem_max = 114688
net.core.rmem_max = 114688
net.core.wmem_default = 114688
net.core.rmem_default = 114688

有关数据同步的更多信息

到目前为止的答案让我觉得有两件事正在发生:

  1. 操作系统读取缓冲区已满。但是如果 CPU 较低,这不应该发生
  2. 但是如果线程正在等待其他事件并且因此读取套接字的速度不够快,则可能会发生#1。

日志记录可能是个问题,我会尝试将其关闭并报告结果。然而,可能更重要的是线程之间的队列争用。由于 CPU 较低,线程可能花费大量时间等待对队列的访问。

在这个服务器的第一次迭代中,我试图在锁定数据方面做得很巧妙。服务器速度非常快,但当它达到 800 数据包/秒时就崩溃了。当前版本锁定整个队列。也许我需要一种更好的方法来同步线程。

问题已回答

我在这里得到的信息非常有帮助。问题是测试客户端的一个愚蠢的错误,但进行调查帮助我消除了此处建议的原因。

仅供引用,这是我的结果。一旦我解决了客户端的问题,服务器每秒接受大约 800 个数据包,CPU 利用率为 70%。我已将操作系统读/写缓冲区从 128K 增加到 12MB。我没有测试读取缓冲区是否已满。我怀疑操作系统读取缓冲区是一个问题,因为在最高速度下,服务器读取线程仍然在每 10 次或 20 次读取时短时间阻塞读取。

800 数据包/秒仍然太慢,所以我从服务器上删除了日志记录。这产生了巨大的变化。服务器能够以 70% 的 CPU 利用率从 1400 多个客户端接收 2900 条消息/秒。

我还对读取线程是否在等待锁进行了一些测试。即使在最高速度下,我发现它的等待时间也永远不会超过 1 毫秒,所以它不是 2900 条消息/秒的因素。也许它会在更快的 CPU 上运行。

此时服务器受 CPU 限制,要找到下一个瓶颈,我需要使用更强大的 CPU。感谢您的帮助!

最佳答案

丢失的最可能原因是 UDP 套接字的传入数据包缓冲区在您的第一个线程可以清空它之前已满;缓冲区已满时收到的任何传入 UDP 数据包都将被丢弃。

第一个线程不能足够快地清空缓冲区以防止它填满的最可能原因是其他东西将它从 CPU 中拖出太久......因为听起来你正在运行单核 CPU,很可能就是这种情况。您可能想尝试将第二个和第三个线程设置为较低的优先级(以便第一个线程在出现争用时获得 CPU 优先权)并查看是否有帮助。如果这还不够好,您可以将您的进程设置为 SCHED_RR“实时”优先级,以确保操作系统中运行的任何其他进程不会使您的第一个线程远离 CPU。 (当然,您仍然可以以较低的优先级运行其他线程,因为它们何时执行并不重要)。

关于linux - Linux 上的 UDP 服务器应用无法接收来自超过 150 个客户端的数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13729005/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com