背景信息:
某用户反馈通过ingress建立的websocket长链接,总是会被断开,影响他们的研发平台的使用,导致业务上线受阻
思考:
1,ingress是7层的代理,客户端的请求到业务pod时,至少是两段请求
client <--> ingress ingress <--> app pod
2,正常fin结束会话一般都是程序主动,要证明这个问题结合第一条做两段抓包,在ingress上抓客户端建联 以及ingress到后端业务pod的建联报文
3,websocket是否有特殊设置?
分析问题:
先抓包,然后登陆ingress controller的pod里面观察流量在哪个pod里面
客户端连接过来后会起(或者复用)一个连接去后端业务的8082端口
抓包条件可以设置为 客户端真实ip 以及8082端口
tcpdump -i any host 58.34.83.130 or port 8082 -s0 -w c2i2p.pcap
分析报文:
客户端抓包
ingress入方向抓包
ingress去后端业务pod方向抓包
客户端到slb slb到ingress ingress到业务pod,是ingress 即发给业务pod finack 又发给前端finack
实锤ingress controller关闭的连接,那么有哪些参数可以影响链接的关闭?
proxy-read-timeout
proxy-send-timeout
worker_shutdown_timeout
调整以上参数后 断开的时间似乎有所延长,从十来分钟增长到15分钟左右,不满足客户预期,继续分析
开启ingress controller debug日志继续分析:
configmap里面添加该配置
error-log-level: debug
开启日志后复现继续分析
开启debug后,从建联的连接上入手找到处理这个session的线程往下分析,中间的数字 一个是nginx worker id 一个是 connection id
从日志看到最近一次请求到了函数ngx_http_terminate_request -- ngx_http_upstream_cleanup -- ngx_http_upstream_finalize_request --ngx_http_upstream_free_keepalive_peer 看不到调用方
既然看不到调用方,升级版本行不行?
尝试使用1.x版本的ingress controller ,依然会有断开的情况
视线重新回到keepalive上,怀疑用户的应用keepalive没生效或者设置有问题,但是从抓包看 间隔15秒的keepalive 很规律,也都有回复
考虑从系统层面做keepalive的优化试试
net.ipv4.tcp_keepalive_intvl = 30 保活间隔30秒
net.ipv4.tcp_keepalive_probes = 90 总共保活九十次
net.ipv4.tcp_keepalive_time = 60 连接空闲60s后开启保活
增加系统级别的优化后 有所好转延长至2小时以上,但是还会时不时断开
与用户协商后,升级生产环境到1.x,使用内核优化参数,长链接依然频繁断开
继续分析,发现出问题时,ingress的连接存在shutdown的状态
worker_shutdown_timeout 超时后强制关闭对应的worker上的连接
Configures a timeout for a graceful shutdown of worker processes. When the time expires, nginx will try to close all the connections currently open to facilitate shutdown.
触发条件:
nginx reload 即 configmap 以及 ingress的增删改 。。。
一顿debug猛如虎,一看结果两块五