为什么 tcpdump 记录数据包之后还会丢失数据包?

为什么 tcpdump 记录数据包之后还会丢失数据包?

我们遇到了一些奇怪的数据包丢失,想知道其原因。

我们有一个图像服务器和一个用于强调图像服务器的服务器。两者都位于同一个数据中心

首先,我们运行这样的负载测试(为便于阅读,命令已缩短):

ab -n 50 -c 5 http://testserver/img/de.png

该图像只有大约300字节。结果响应非常快:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       0
Processing:     1    3   0.7      3       4
Waiting:        1    3   0.7      3       3
Total:          1    3   0.7      3       4

当我们增加并发性时,我们会看到一些滞后(为便于阅读,命令已缩短):

sudo ab -n 500 -c 50 http://testserver/img/de.png

并发 50 的结果:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       1
Processing:     2   35 101.6     12     614
Waiting:        2   35 101.6     12     614
Total:          3   36 101.7     12     615

所以我们看到大多数请求都非常快,但其中有一些请求非常慢。

我们用 tcpdump 转储了整个网络流量,发现一些奇怪的重传。

替代文本 http://vygen.de/screenshot1.png

此转储是在图像服务器上进行的!

因此,您会看到包含 GET 请求的初始包(编号 306)已到达图像服务器,但似乎在 tcpdump 记录该包后,该包丢失了。在我看来,这个包并没有到达 tomcat 图像服务器。

200 毫秒后,请求服务器触发重传,之后一切运行正常。

您知道为什么包裹在收到后会丢失吗?

我们的机器均具有:

  • 英特尔(R) 酷睿(TM) i7 CPU 920 @ 2.67GHz
  • 8 GB 内存
  • 以太网控制器:Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express 千兆以太网控制器 (rev 02)
  • Debian 版本 5.0.5

因此我们没有遇到任何有关内存或 CPU 负载的问题。

不久前,我们的网卡控制器出现了一些问题。我们通过使用不同的驱动程序解决了这个问题,现在我们使用 r8168 而不是 r8169

但我们在使用英特尔网卡时也遇到了同样的数据包丢失问题 - 以太网控制器:英特尔公司 82541PI 千兆以太网控制器(修订版 05)

因此,我们在同样的机器但不同的以太网卡上看到了同样的问题。

到目前为止,我认为数据包丢失只会发生在线的服务器之间,当数据包损坏或类似情况时。

我们确实想知道 tcpdump 记录这些数据包后,这些数据包丢失的原因可能是什么。

非常感谢您的帮助。

答案1

我们找到了问题的根本原因。我们的 tomcat server.xml 中的 acceptCount 为 25。

acceptCount 的记录如下:

接受计数

当所有可能的请求处理线程都在使用时,传入连接请求的最大队列长度。队列已满时收到的任何请求都将被拒绝。默认值为 100。

但这并不是关于 acceptCount 的全部内容。简而言之:acceptCount 是打开套接字时的 backlog 参数。因此,即使并非所有线程都处于繁忙状态,此值对于监听 backlog 也很重要。如果请求以更快的速度进入,则 tomcat 可以接受它们并将其委托给等待线程,这一点很重要。默认的 acceptCount 为 100。这仍然是一个很小的值,无法满足请求的突然高峰。

我们用 apache 和 nginx 检查了同样的情况,也出现了奇怪的丢包现象,但并发值更高。apache 中的对应值是 ListenBacklog,默认值为 511。

但是,在 debian(和其他基于 Linux 的操作系统)中,backlog 参数的默认最大值是 128。

$ sysctl -a | grep somaxc
net.core.somaxconn = 128

因此,无论您输入 acceptCount 还是 ListenBacklog,它都不会超过 128,除非您更改 net.core.somaxconn

对于非常繁忙的 Web 服务器,128 是不够的。您应该根据需要将其更改为 500、1000 或 3000。

将 acceptCount 设置为 1000 并将 net.core.somaxconn 设置为 1000 后,我们不再有那些丢包的情况。(现在我们在其他地方遇到了瓶颈,但这是另一个故事……)

答案2

200ms 是默认的 TCP 重传超时 (RTO);在RFC2988,尽管没有定义该最小值)。

所以... 某些东西被延迟或丢失,导致 RTO 被触发。也许数据包被延迟,从而触发了 RTO,但 wireshark 在数据包解析/渲染过程中将其平滑了?您应该更详细地调查跟踪。

您可以提供一张更大的数据包捕获图像吗?

相关内容