1. 程式人生 > 實用技巧 >記一次linux tcp和kafka調參

記一次linux tcp和kafka調參

線上kafka叢集事故,很快根據kafka和dmesg linux核心日誌定位到表面原因,

[Tue Jun 30 19:22:29 2020] TCP: out of memory -- consider tuning tcp_mem
[Tue Jun 30 19:22:31 2020] TCP: out of memory -- consider tuning tcp_mem
[Tue Jun 30 19:22:31 2020] TCP: out of memory -- consider tuning tcp_mem
[Tue Jun 30 19:22:32 2020] TCP: out of memory -- consider tuning tcp_mem
[Tue Jun 
30 19:22:32 2020] TCP: out of memory -- consider tuning tcp_mem [Tue Jun 30 19:22:35 2020] TCP: out of memory -- consider tuning tcp_mem [Tue Jun 30 19:22:36 2020] TCP: out of memory -- consider tuning tcp_mem [Tue Jun 30 19:22:46 2020] TCP: out of memory -- consider tuning tcp_mem

“TCP: out of memory -- consider tuning tcp_mem”,核心報OOM,同時刻kafka也拋OOM異常,整個叢集不可用。

這裡有2個點待探究,

1. 什麼原因導致的 TCP: out of memory

2. 一個broker的OOM為何導致叢集不可用。TCP: out of memory現象消失後,kafka為何沒從假死中恢復

由於dmesg是核心列印的資訊,從github linux核心程式碼中找到程式碼位置,https://github.com/torvalds/linux/blob/cb8e59cc87201af93dfbb6c3dccc8fcad72a09c2/include/net/tcp.h#L282

static inline bool tcp_out_of_memory(struct sock *sk)
{
    
if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF && sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2)) return true; return false; }

異常原因是 sk->sk_wmem_queued > SOCK_MIN_SNDBUF。TCP的傳送緩衝區滿了,檢視其預設tcp_mem配置為:

# sysctl -a |grep tcp_mem

net.ipv4.tcp_mem = 377607503478755214。 單位是page,1page = 4096位元組(# getconf PAGESIZE4096)

檢視實際的記憶體使用:

# cat /proc/net/sockstat
sockets: used 2328
TCP: inuse 458 orphan 19 tw 6529 alloc 2115mem 25693(無法還原故障現場)
UDP: inuse 5 mem 22
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

按照dmesg提示,猜測可以通過調整一個較小的tcp_mem來複現故障。

# vim /etc/sysctl.conf

net.ipv4.tcp_mem = 1 2 2

執行一段時間後,故障復現。kafka叢集OOM不可用,同時dmesg報相同的錯誤資訊“TCP: out of memory -- consider tuning tcp_mem”。

所以OOM產生的原因是,tcp_mem緩衝區設定較小,網路擁堵導致sk_wmem_queued訊息堆積。暫時的規避措施是調大tcp_mem。

kafka未從故障中恢復過來,可能是因為其Bug導致,可以加一項啟動引數"-XX:+ExitOnOutOfMemoryError"讓其在OOM時自動退出,同時配置監控和自動拉起機制,保證叢集可用性。

參考:

https://blog.tsunanet.net/2011/03/out-of-socket-memory.html, 分析了TCP out of memory可能的原因

https://unix.stackexchange.com/questions/551444/what-is-the-difference-between-sock-sk-wmem-alloc-and-sock-sk-wmem-queued,介紹了sk_wmem_queue是什麼,sk_wmem_queue滿是TCP OOM的原因

https://github.com/torvalds/linux/blob/cb8e59cc87201af93dfbb6c3dccc8fcad72a09c2/include/net/tcp.h#L282,dmesg異常列印的linux kernel程式碼位置