我正在运行一组负载测试来确定以下设置的性能:
Node.js test suite (client) --> StatsD (server) --> Graphite (server)
简而言之,node.js 测试套件每 x 秒向位于另一台服务器上的 StatsD 实例发送一定数量的指标。然后,StatsD 每秒将指标刷新到位于同一台服务器上的 Graphite 实例。然后,我查看测试套件实际发送了多少指标以及 Graphite 收到了多少指标,以确定测试套件和 Graphite 之间的数据包丢失。
但是我注意到,有时数据包丢失率非常高(请注意,数据包是通过 UDP 协议发送的),范围从 20% 到 50%。因此,我开始调查这些数据包丢失的位置,认为这可能是 StatsD 的一些性能问题。因此,我开始在系统的每个部分记录指标,以追踪丢失的位置。这就是事情变得奇怪的地方。
我在用着tcpdump创建一个捕获文件,测试完成后我会检查该文件。但是,每当我使用 tcpdump 运行测试时,数据包丢失几乎不存在!看起来 tcpdump 以某种方式提高了我的测试性能,但我不知道它为什么以及如何做到这一点。我正在运行以下命令来记录服务器和客户端上的 tcpdump 消息:
tcpdump -i any -n port 8125 -w test.cap
在一个特定的测试案例中,我每秒发送 40000 个指标。运行 tcpdump 的测试数据包丢失率约为 4%,而未运行 tcpdump 的测试数据包丢失率约为 20%
两个系统均作为 Xen VM 运行,设置如下:
- 英特尔至强 E5-2630 v2 @ 2.60GHz
- 2GB 内存
- Ubuntu 14.04 x86_64
我已经检查过的潜在原因如下:
- 增加 UDP 缓冲区接收/发送大小。
- CPU 负载影响测试。(客户端和服务器端的最大负载为 40-50%)
- 在特定接口而不是‘任何’接口上运行 tcpdump。
- 运行带有‘-p’的 tcpdump 来禁用混杂模式。
- 仅在服务器上运行 tcpdump。这导致数据包丢失 20%,但似乎不会影响测试。
- 仅在客户端上运行 tcpdump。这可提高性能。
- 将 netdev_max_backlog 和 netdev_budget 增加到 2^32-1。这没什么区别。
- 尝试了每个网卡上所有可能的混杂模式设置(服务器开启而客户端关闭、服务器关闭而客户端开启、两者同时开启、两者同时关闭)。这没有任何效果。
答案1
当 tcpdump 运行时,它会相当迅速地读取传入的帧。我的假设是,NIC 的数据包环形缓冲区设置可能有点小;当 tcpdump 运行时,它会更及时地清空。
如果你是 Red Hat 用户,那么这篇支持文章非常有用数据包接收概述。其中有些内容我认为你还没有考虑到。
考虑您的系统如何处理 IRQ;考虑增加网络接口的“dev_weight”(意味着从 NIC 读取更多数据包到用户空间);查看应用程序读取套接字的频率(它是否可以使用专用线程,是否存在有关可扩展性的已知问题/解决方法)。
增加 NIC 帧缓冲区(使用ethtool
命令--查看--set-ring
等参数)。
查看“接收方扩展”并使用至少那么多的接收线程来读取流量。
我想知道 tcpdump 是否在做一些很酷的事情,比如使用内核支持数据包环形缓冲区。这将有助于解释您所看到的行为。
答案2
您使用的是哪种电源调速器?我使用“按需”或“保守”调速器时也看到过类似的行为。
尝试使用“性能”调节器并禁用服务器 BIOS 中的任何省电功能。
它改变了什么吗?
答案3
另一种方法是ip_conntarck
模块,你确定你的linux-box可以接受新的连接吗?通过以下方式测试:
root@debian:/home/mohsen# sysctl net.ipv4.netfilter.ip_conntrack_max
net.ipv4.netfilter.ip_conntrack_max = 65536
root@debian:/home/mohsen# sysctl net.ipv4.netfilter.ip_conntrack_count
net.ipv4.netfilter.ip_conntrack_count = 29
你必须测试
net.ipv4.netfilter.ip_conntrack_max > net.ipv4.netfilter.ip_conntrack_count
如果 max == count ,则表示您的最大连接数已满,并且您的 linux-box 无法接受新连接。
如果您没有 ip_conntrack,则可以通过以下方式轻松加载modprobe ip_conntrack
答案4
我怀疑接收方根本无法处理数据包速率,原因如下:
使用 tcpdump在客户端上减少数据包丢失:tcpdump 正在减慢客户端的速度,因此服务器看到的打包速率要低得多,但仍然可以部分处理。您应该能够通过检查客户端和服务器上的 RX/TX 数据包计数器来确认这一假设
你提到你增加了 UDP 缓冲区接收/发送大小,你能详细说明一下怎么做吗?重要的是在服务器上更改 rmem_max和rmem_default,例如:
sysctl -w net.core.rmem_max=524287 sysctl -w net.core.wmem_max=524287 sysctl -w net.core.rmem_default=524287 sysctl -w net.core.wmem_default=524287
测试您的设置
停止 statsd 和节点应用程序,然后使用系统空闲防火墙测试网络/内核可以处理的数据包速率。如果您可以使用 iperf 传输 40K 数据包/秒,但不能使用 statsd,那么您应该集中精力调整 statsd。
其他可调参数
还要记得调整net.core.netdev_max_backlog:当特定接口接收数据包的速度比内核处理数据包的速度快时,允许排队的最大数据包数。