Celery Worker结束后RabbitMQ TCP连接未关闭,无心跳发送
RabbitMQ与Celery Worker残留TCP连接问题
信息说明
任意Celery Worker运行结束后,RabbitMQ代理服务器上会残留一个挂起的TCP连接。在Google Cloud Platform中使用抢占式实例作为处理流水线的Worker时,连接数量会不断累积,最终导致Debian服务器内存耗尽。
场景概述
- Worker启动并连接RabbitMQ,建立2条TCP连接
- Worker运行结束,实例被停止并移除
- Worker已终止,连接A被关闭,但连接B仍残留
环境版本
该问题在两组不同版本的RabbitMQ和Erlang环境下均出现:
- RabbitMQ 3.7.17 + Erlang 22.0.7-1
- RabbitMQ 3.10.14 + Erlang 25.0.4-1
详细场景
- Worker启动并连接RabbitMQ,建立2条TCP连接。从Worker的IP地址到RabbitMQ实例的两个不同端口建立了两条连接
Listing connections ... user peer_host peer_port state epic 10.240.60.56 A running epic 10.240.60.56 B running
netstat显示有两条连接指向RabbitMQ(端口5672)
- Worker运行结束,实例被停止并移除
端口36654的连接情况,tcpdump捕获到以下数据包:
# 36654 Worker从端口B发出的最后一个数据包 17:05:24.395092 IP 10.240.50.2.5672 > 10.240.60.56.B: Flags [P.], seq 2769:2790, ack 48864, win 273, options [nop,nop,TS val 991690205 ecr 1201716502], length 21 # Broker对端口B的最后一条消息回复ACK 17:05:24.395252 IP 10.240.60.56.B > 10.240.50.2.5672: Flags [.], ack 2790, win 507, options [nop,nop,TS val 1201716502 ecr 991690205], length 0 # Broker尝试向Worker端口A重发"4232:4240"的最后8字节? 17:05:29.922421 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991691587 ecr 1201692028], length 8 17:05:30.127621 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991691639 ecr 1201692028], length 8 17:05:30.335615 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991691691 ecr 1201692028], length 8 17:05:30.771599 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991691800 ecr 1201692028], length 8 17:05:31.603593 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991692008 ecr 1201692028], length 8 17:05:33.267555 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991692424 ecr 1201692028], length 8 17:05:36.563603 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991693248 ecr 1201692028], length 8 17:05:43.219601 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991694912 ecr 1201692028], length 8 17:05:56.531566 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991698240 ecr 1201692028], length 8 17:06:23.923626 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [P.], seq 4232:4240, ack 1324, win 58, options [nop,nop,TS val 991705088 ecr 1201692028], length 8 # 重试失败后关闭连接A 17:06:59.920635 IP 10.240.50.2.5672 > 10.240.60.56.A: Flags [R.], seq 4240, ack 1324, win 58, options [nop,nop,TS val 991714087 ecr 1201692028], length 0
- Worker已终止,连接A被关闭,但连接B仍残留
RabbitMQ显示仍有一条连接,netstat也显示存在指向5672端口的连接:
Listing connections ... user peer_host peer_port state epic 10.240.60.56 B running
该连接会一直残留,直到重启RabbitMQ或服务器。
期望RabbitMQ能在残留的连接上发送心跳,从而发现对等端已不存在并关闭连接,但实际并未发送心跳。
已尝试操作
- 升级RabbitMQ和Erlang版本,问题依旧→无效果
- 将内核TCP保活时间从60秒降低至5秒(
net.ipv4.tcp_keepalive_time)→无效果 - 将RabbitMQ心跳间隔从60秒降低至10秒→无效果
调试工具
使用以下命令查看连接:
sudo rabbitmqctl list_connections
以及(RabbitMQ运行在5672端口):
sudo netstat -ntpo | grep -E ':5672\>'|wc -l
使用tcpdump结合IP+端口来区分两条不同的连接,查看数据包发送情况。为便于阅读,将Worker的两个端口替换为A和B
内容的提问来源于stack exchange,提问作者eklockare
相关产品推荐
相关产品推荐

