celery与flask eventlet结合使用导致backend连接数不释放
目录
问题描述
flask提供http接口调用celery任务, 并且flask使用eventlet方式运行
而celery采用redis作为backend
运行一段时间后发现redis连接数超过1000以上
celery竟然未释放释放redis连接
为什么?
代码片段
调用方式很正常,并没有特殊地方
def send_task(self, name, timeout=60, **kwargs):
t = self.send_task(name, **kwargs)
return t.get(timeout=timeout)
问题探索
1.修改celery连接池等参数,然后并没有什么用
2.搜索资料,基本没有这种场景的问题
3.逐行调试celery源码,发现了问题所在
问题原因
celery的backend被缓存在threading.local()中, 而这个地方的threading被绿化了,实际上用的是eventlet.corolocal.local
此处的local缓存效果失效,所以每次都是新建backend连接
解决方法
自定义celery, 将backend缓存在属性中
class XXCelery(Celery):
def init_app(self):
self._my_backend = None
def _get_backend(self):
"""
修复celery应用 bug
"""
if self._my_backend is None:
self._my_backend = super(XXCelery, self)._get_backend()
return self._my_backend
问题延申
-
eventlet.monkey_patch()应该只绿化thread了, celery中的threading.local在什么时候被绿化?
-
每次新建的backend没被回收吗, 难道不自动释放redis连接?
问题已解决, 还有几个疑问没弄清, 节约发量,不想了.
佛說大乘無量壽莊嚴清淨平等覺經pdf 净土大经科注2014-doc 此生必看的科学实验-水知道答案 印光大师十念法(胡小林主讲第1集)