Linux 网络调整如何防止 tcp rcvpruned 和 backlogdrop?

Linux 网络调整如何防止 tcp rcvpruned 和 backlogdrop?

我的 HBase 集群中的数据节点不时触发一些 tcp rcvpruned 和 backlog 丢弃:

在此处输入图片描述

似乎至少有两个角度可以解决这个问题:

  1. 调整 HBase/HDFS 等...以便不会触发这些
  2. 调整 Linux 网络堆栈以便能够处理这些

我对进一步了解这两个指标以及对这两条路径的任何可行建议感兴趣。有人能就具体的下一步行动提出建议吗?

答案1

tcp_v4_rcv[0] 调用sk_add_backlog,如果失败则递增TCPBacklogDrop

2014         } else if (unlikely(sk_add_backlog(sk, skb,
2015                                            sk->sk_rcvbuf + sk->sk_sndbuf))) {
2016                 bh_unlock_sock(sk);
2017                 NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
2018                 goto discard_and_relse;
2019         }

sk_add_backlogsk_rcvqueues_full仅当[1]时才失败:

801 /* The per-socket spinlock must be held here. */
802 static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb,
803                                               unsigned int limit)
804 {
805         if (sk_rcvqueues_full(sk, skb, limit))
806                 return -ENOBUFS;
807 
808         __sk_add_backlog(sk, skb);
809         sk->sk_backlog.len += skb->truesize;
810         return 0;
811 }

底层函数__sk_add_backlog最近[2]允许至少一个数据包通过:

+ * Do not take into account this skb truesize,
+ * to allow even a single big packet to come.

我认为将该补丁应用于内核应该可以解决问题。您也可以尝试增加操作系统和应用程序中的默认 rcv 缓冲区大小(setsockopt SO_RCVBUF

您的第二个问题是关于RcvPruned- Linux 增加tcp_prune_queue[3] 中的统计信息。该函数通常在套接字超出其 rcv 限制时调用。因此,您可以再次增加rmem/SO_RCVBUF和/或调整应用程序以更频繁地进行 read() 调用(我假设您的丢失与 Java 的 Stop-The-World GC 暂停密切相关。因此,请调整您的 GC)。

[0]http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c?v=3.15#L2014
[1]http://lxr.free-electrons.com/source/include/net/sock.h?v=3.15#L802
[2]https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=0fd7bac6b6157eed6cf0cb86a1e88ba29e57c033
[3]http://lxr.free-electrons.com/source/net/ipv4/tcp_input.c?v=3.15#L4662

相关内容