记一次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 = 377607 503478 755214。 单位是page,1page = 4096字节(# getconf PAGESIZE 4096)
查看实际的内存使用:
# cat /proc/net/sockstat
sockets: used 2328
TCP: inuse 458 orphan 19 tw 6529 alloc 2115 mem 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代码位置
原文地址:https://www.cnblogs.com/gm-201705/p/13282541.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux基础命令之mktemp详解
- TP3.2.3框架使用CKeditor编辑器在页面中上传图片的方法分析
- Laravel5.1 框架模型一对一关系实现与使用方法实例分析
- Linux中怎么查看已挂载的文件系统类型详解
- PHP实现笛卡尔积算法的实例讲解
- TP5框架简单登录功能实现方法示例
- 使用 Apache Web 服务器配置两个或多个站点的办法
- 详解laravel passport OAuth2.0的4种模式
- Apache Web 服务器的安装配置办法
- thinkphp5实现微信扫码支付
- laravel框架实现后台登录、退出功能示例
- Laravel5.1 框架数据库操作DB运行原生SQL的方法分析
- Linux查看进程的所有信息的办法示例
- PHP配合fiddler抓包抓取微信指数小程序数据的实现方法分析
- Python基于traceback模块获取异常信息