Python中关于Celery和Redis的CLOSE_WAIT连接问题如何解决

使用 celery 时,用 redis 作为 result_backend 和 broker,配置是 CELERY_RESULT_BACKEND = ‘redis://localhost:6379/2’,CELERY_BROKER_URL = ‘redis://localhost:6379/0’。执行任务时,一开始会生成很多 ESTABLISHED 的 tcp 连接无法回收,connected_clients 不断累积。如:uwsgi 31657 root 2263u IPv6 918201 0t0 TCP localhost:39098->localhost:6379 (ESTABLISHED)。
后来在 redis 的配置中添加了 timeout=60,redis 中利用 info clients 命令查询发现,connected_clients 数量过一段时间确实会降下来;但是利用 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'命令查询发现,又产生大量的 CLOSE_WAIT 的 tcp6 连接,用 lsof -i 命令查看连接结果是,如:uwsgi 31657 root 3289u IPv6 934052 0t0 TCP localhost:41230->localhost:6379 (CLOSE_WAIT)。(项目中,没有使用任何连接池)该怎么解决大量 CLOSE_WAIT 连接问题? 头大了好几天了,望大佬指点一下
Python中关于Celery和Redis的CLOSE_WAIT连接问题如何解决


1 回复

这个问题我遇到过,CLOSE_WAIT连接堆积通常是因为Celery任务完成后没有正确关闭Redis连接。

核心原因是TCP连接关闭时,客户端(Celery)收到了服务端(Redis)的FIN包,但客户端没有发送自己的FIN包来完全关闭连接,导致连接卡在CLOSE_WAIT状态。

解决方案:

  1. 配置Celery的连接池设置(最有效):
# celery.py 或配置中
app.conf.broker_pool_limit = 10  # 减少连接池大小
app.conf.broker_connection_timeout = 30  # 连接超时
app.conf.broker_connection_retry = True
app.conf.broker_connection_max_retries = 3
  1. 确保任务中正确释放资源
from celery import Task

class BaseTask(Task):
    def after_return(self, status, retval, task_id, args, kwargs, einfo):
        # 任务结束后清理连接
        from celery import current_app
        if current_app.connection_for_read():
            current_app.connection_for_read().close()
  1. 使用连接复用
# 在任务中重用连接而不是新建
from celery import current_app

@task
def my_task():
    with current_app.pool.acquire() as connection:
        # 使用connection进行操作
        pass
  1. 监控和清理(临时方案):
# 查看CLOSE_WAIT连接
netstat -an | grep CLOSE_WAIT | grep 6379

# 在Python中定期清理
import redis
from celery import current_app

def cleanup_connections():
    if hasattr(current_app, 'pool'):
        current_app.pool.disconnect()

关键点: 主要调整broker_pool_limit和确保连接正确关闭,大多数情况下减少连接池大小就能解决。

总结:调整连接池配置并确保连接正确释放。

回到顶部