- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我已经在 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
有关数据同步的更多信息
到目前为止的答案让我觉得有两件事正在发生:
日志记录可能是个问题,我会尝试将其关闭并报告结果。然而,可能更重要的是线程之间的队列争用。由于 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/
我有一个存储结构向量的应用程序。这些结构保存有关系统上每个 GPU 的信息,如内存和 giga-flop/s。每个系统上有不同数量的 GPU。 我有一个程序可以同时在多台机器上运行,我需要收集这些数据
我很好奇 MPI 中缺少此功能: MPI_Isendrecv( ... ); 即,非阻塞发送和接收,谁能告诉我其省略背后的基本原理? 最佳答案 我的看法是 MPI_SENDRECV存在是为了方便那些想
当我用以下方法监听TCP或UDP套接字时 ssize_t recv(int sockfd, void *buf, size_t len, int flags); 或者 ssize_t recvfrom
SUM:如何在 azure 事件网格中推迟事件触发或事件接收? 我设计的系统需要对低频对象状态(创建、启动、检查长时间启动状态、结束)使用react。它看起来像是事件处理的候选者。我想用azure函数
我正在 MPI 中实现一个程序,其中主进程(等级 = 0)应该能够接收来自其他进程的请求,这些进程要求只有根才知道的变量值。如果我按等级 0 进行 MPI_Recv(...),我必须指定向根发送请求的
我正在学习DX12,并在此过程中学习“旧版Win32”。 我在退出主循环时遇到问题,这似乎与我没有收到WM_CLOSE消息有关。 在C++,Windows 10控制台应用程序中。 #include
SUM:如何在 azure 事件网格中推迟事件触发或事件接收? 我设计的系统需要对低频对象状态(创建、启动、检查长时间启动状态、结束)使用react。它看起来像是事件处理的候选者。我想用azure函数
我想编写方法来通过号码发送短信并使用编辑文本字段中的文本。发送消息后,我想收到一些声音或其他东西来提醒我收到短信。我怎样才能做到这一点?先感谢您,狼。 最佳答案 这个网站似乎对两者都有很好的描述:ht
所以我正在用 Java 编写一个程序,在 DatagramSocket 和 DatagramPacket 的帮助下发送和接收数据。问题是,在我发送数据/接收数据之间的某个时间 - 我发送数据的程序中的
我是 Android 编程新手,我正在用 Java 编写一个应用程序,该应用程序可以打开相机拍照并保存。我通过 Intents 做到了,但看不到 onActivityResult 正在运行。 我已经在
我有一个套接字服务器和一个套接字客户端。客户端只有一个套接字。我必须使用线程在客户端发送/接收数据。 static int sock = -1; static std::mutex mutex; vo
我正在尝试使用 c 中的套接字实现 TCP 服务器/客户端。我以这样的方式编写程序,即我们在客户端发送的任何内容都逐行显示在服务器中,直到键入退出。该程序可以运行,但数据最后一起显示在服务器中。有人可
我正在使用微 Controller 与 SIM808 模块通信,我想发送和接收 AT 命令。 现在的问题是,对于某些命令,我只收到了我应该收到的答案的一部分,但对于其他一些命令,我收到了我应该
我用c设计了一个消息传递接口(interface),用于在我的系统中运行的不同进程之间提供通信。该接口(interface)为此目的创建 10-12 个线程,并使用 TCP 套接字提供通信。 它工作正
我需要澄清一下在套接字程序中使用多个发送/接收。我的客户端程序如下所示(使用 TCP SOCK_STREAM)。 send(sockfd,"Messgfromlient",15,0);
我正在构建一个真正的基本代理服务器到我现有的HTTP服务器中。将传入连接添加到队列中,并将信号发送到另一个等待线程队列中的一个线程。此线程从队列中获取传入连接并对其进行处理。 问题是代理程序真的很慢。
我正在使用 $routeProvider 设置一条类似 的路线 when('/grab/:param1/:param2', { controller: 'someController',
我在欧洲有通过 HLS 流式传输的商业流媒体服务器。http://europe.server/stream1/index.m3u8现在我在美国的客户由于距离而遇到一些网络问题。 所以我在美国部署了新服
我有一个长期运行的 celery 任务,该任务遍历一系列项目并执行一些操作。 任务应该以某种方式报告当前正在处理的项目,以便最终用户知道任务的进度。 目前,我的django应用程序和celery一起坐
我需要将音频文件从浏览器发送到 python Controller 。我是这样做的: var xmlHttp = new XMLHttpRequest(); xmlHttp.open( "POST",
我是一名优秀的程序员,十分优秀!