Subscribe too much celery-task-meta using Redis backend
问题原因:1、publish消息订阅 subscribe发布机制。服务端pub断开,或者主动杀死,如果客户端主动断开或者杀死的话,还是占用链接数的,客户端sub不会断开,但不会接受消息,占用连接数;2、通过redis查看的info clients连接数越来越多,不多久就会报连接数太高的异常,查看client list会发现有很多空闲的id,addr,idle;3、如果用的是异步任务,主要是celery版本过低,4.2及以下都会有这种情况产生。
Redis发布功能和订阅机制的原理分析
Redis 通过 PUBLISH 、 SUBSCRIBE 和 PSUBSCRIBE 等命令实现发布和订阅功能。UNSUBSCRIBE 命令和 PUNSUBSCRIBE 负责退订给定的频道或模式。
发布和订阅机制
当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher)。
而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE 命令接收信息的时候,我们称这个客户端为订阅者(subscriber)。
为了解耦发布者(publisher)和订阅者(subscriber)之间的关系,Redis 使用了 channel (频道)作为两者的中介 —— 发布者将信息直接发布给 channel ,而 channel 负责将信息发送给适当的订阅者,发布者和订阅者之间没有相互关系,也不知道对方的存在:
Redis发布与订阅机制的使用场景
1、异步消息通知
2、任务通知
3、参数刷新加载
解决方案
1、禁用后端结果或将sql数据库用作后端结果。
2、改用kafka等异步,rabbitMQ等队列
3、定时删除空闲时间过长的连接,附代码(Python版本,Java也有)
import redis
conn = redis.StrictRedis(host='0.0.0.0', port=6379, db=0, password='123456')
info = conn.client_list() # 获取redis的链接详情
for i in info:
if i.get('idle') >= 1500: # 删除空闲时间大于1500S的连接
try:
conn.client_kill(i.get('addr').encode()) # 删除连接的ip地址,这条连接就会断开
except Exception as e:
continue
else:
continue
4、在这台服务器上写crontab定时任务,shell脚本定时获取删除。