Hbaseクラスター内のデータノードがtcprcvprunedをトリガーし、バックログが時々ドロップします。
これにアプローチするには、少なくとも2つの角度があるようです。
私は、これら2つの指標をさらに理解し、これら2つのパスのいずれかに関する実用的なアドバイスに興味があります。誰かが具体的な次のステップについてアドバイスできますか?
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_backlog
は、sk_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]で、少なくとも1つのパケットを通過させることができました。
+ * Do not take into account this skb truesize,
+ * to allow even a single big packet to come.
そのパッチをカーネルに適用すると、問題が解決するはずです。また、OSとアプリケーションの両方でデフォルトのrcvバッファサイズを増やしてみることもできます(setsockopt
SO_RCVBUF
)
そして、RcvPruned
に関する2番目の質問-Linuxは、tcp_Prune_queue
[3]内でその統計をインクリメントします。この関数は通常、ソケットがrcv制限を超えたときに呼び出されます。したがって、rmem
/SO_RCVBUF
を増やすか、アプリケーションを調整してread()呼び出しをより頻繁に行うことができます(ドロップはJavaのStop-The-WorldGCと密接に関連していると思います)一時停止します。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=0fd7bac6b6157eed6cf0cb86a1e88ba29e57c0
[3] http://lxr.free-electrons.com/source/net/ipv4/tcp_input.c?v=3.15#L4662