Linuxnetworking调优,以防止TCP rcvpruned和backlogdrop?

我的hbase集群中的datanode会不时触发一些tcp rcvpruned和backlog drop:

在这里输入图像说明

似乎至less有两个angular度来解决这个问题:

  1. 调整HBase / HDFS等等,这样不会触发
  2. 调整Linuxnetworking堆栈以处理这些问题

我有兴趣了解这两个指标,并在这两条path上的任何可行的build议。 任何人都可以build议具体的下一步?

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_rcvqueues_full [1]: sk_add_backlog失败

 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]允许至less一个数据包通过:

 + * 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]中的stat tcp_prune_queue 1。 这个函数通常在套接字超过rcv的限制时被调用。 所以你可以增加你的rmem / SO_RCVBUF和/或调整应用程序来更频繁地进行read()调用(我假设你的drop与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