Linux TCP: 发送端高Send-Q,接收端零Recv-Q

15

如何解决以下问题:

  1. 两台计算机之间有一个TCP套接字
  2. 在一些成功的双向通信后,发送方应用程序在写入套接字时被卡住,而接收方则在从中读取时被卡住
  3. netstat 报告发送方套接字上的高 Send-Q(几兆字节)(即使等待了几个小时后该值也不会改变)
  4. netstat 报告接收方套接字上的 Recv-Q 为零
  5. tcpdump 报告套接字上唯一的活动是来自发送方没有数据的周期性(每两分钟)ACK和来自接收方没有数据的立即ACK响应

为什么发送方计算机没有尝试将排队的数据发送给接收方?


4
你没有发布任何代码,所以很难得到更多信息。尝试检查那个周期性的ACK(可能是TCP保活)的内容,以获取当前TCP窗口大小。 - selbie
1
是的,它必须是TCP保持活动状态。每次发送方窗口大小为40822,接收方窗口大小为31883。 - Orivej Desh
1
好像接收端有一个bug,没有从套接字中消耗所有的字节。但是你没有发布任何代码,所以无法确定。 - selbie
1
我测试了这个假设,但当接收应用程序无法消耗传入数据时,接收套接字上的 Recv-Q 保持在预期的非零状态。我没有小而可重现的测试用例,我怀疑问题只会在网络暂时丢失一些 IP 数据包时发生。我不要求帮助应用程序代码,因为考虑到数据位于发送方内核缓冲区中,它似乎并没有错,而是需要帮助理解看似不可能的 Linux 内核状态。 - Orivej Desh
@OrivejDesh你能找出这个问题的根本原因吗? - Apoorv
显示剩余2条评论
3个回答

2
在我的情况下,客户端以8KB的块写入数据,服务器试图读取8KB,然后将其写入RAID0磁盘。上传大文件时,我遇到了类似的情况,增加我从服务器套接字读取的数据量有所帮助。我将从套接字读取的内部缓冲区大小提高到1MB(从8 kB),这有所帮助。我不确定是因为RAID还是TCP,但这可能是您想尝试的另一件事情。

2

这更可能是由其他问题引起的,但以下方法可能有所帮助,如果您还没有尝试过(这些数字是示例,请找到您自己的数字):

  1. 估算发送方和接收方文件系统的读写速度以及网络速度,并在rsync中设置适当的带宽限制:--bwlimit=1024(1024 KBps)
  2. 如果发送方和接收方在本地网络中有专用NIC,请增加这些NIC的MTU:ifconfig eth1 mtu 65744
  3. 增加发送方传输队列长度:ifconfig eth1 txqueuelen 4096
  4. 增加内核发送/接收内存:
    将以下内容添加到/etc/sysctl.conf文件中
    net.core.wmem_max=16777216
    net.core.rmem_max=16777216
    net.ipv4.tcp_rmem=4096 262144 16777216
    net.ipv4.tcp_wmem=4096 262144 16777216

    之后运行sysctl -p
  5. 如果您要同步非常大的文件系统,请确保fs.file-max足够大,
    检查方法: sysctl  fs.file-max
    要增加它,在/etc/sysctl.conf文件中添加一行fs.file-max=327679
    在您的rsync用户上运行:ulimit -n 327679

0

这并没有真正回答问题。如果您有不同的问题,可以通过点击提问来提出。如果您想在此问题获得新的答案时得到通知,您可以关注此问题。一旦您拥有足够的声望,您还可以添加悬赏以吸引更多关注。- 来自审核 - Wouter Verhelst

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接