Celery 连接 Redis 报 Connection refused,在 Django 项目里怎么解决?

文章导读
Celery 连接 Redis 报 Connection refused 通常是因为 Redis 服务未启动、网络端口不通或配置地址错误。在 Django 项目中,优先检查 Redis 进程状态和防火墙设置,再核对 CELERY_BROKER_URL 配置。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

Celery 连接 Redis 报 Connection refused 通常是因为 Redis 服务未启动、网络端口不通或配置地址错误。在 Django 项目中,优先检查 Redis 进程状态和防火墙设置,再核对 CELERY_BROKER_URL 配置。

先说结论:绝大多数问题集中在 Redis 服务不可达、密码认证失败或防火墙拦截,核心排查逻辑是“先网络后配置”。

  • 先确认:Redis 服务进程是否运行且端口监听正常
  • 先处理:修正 Django 配置中的连接字符串格式与密码安全性
  • 再验证:观察 Celery Worker 启动日志,确认无 Connection refused 或 NOAUTH 错误

命令速用版

在 Django 应用所在的服务器上执行以下命令,按顺序排查网络与服务状态。

# 1. 检查 Redis 服务状态
systemctl status redis

# 2. 测试 TCP 端口连通性 (推荐 nc,若未安装可尝试 telnet)
nc -zv <host> <port>

# 3. 测试 Redis 协议连通性 (需安装 redis-tools)
redis-cli -h <host> -p <port> -a <password> ping

# 4. Python 脚本验证 (无 redis-cli 时的替代方案)
python -c "import redis; r = redis.Redis(host='<host>', port=<port>, password='<password>'); print(r.ping())"

为什么会这样

Connection refused 错误表明客户端无法在目标 IP 和端口上建立 TCP 连接,核心原因是目标端口没有进程监听或被操作系统防火墙直接拒绝。

在使用 Celery 连接 Redis 时,如果出现该错误,通常是由于 Redis 服务未启动、端口被占用或配置错误导致。Django 启动时不会自动拉起 Celery,调用 task.delay() 只是往消息队列里塞了个任务,没人消费它就永远挂在那里。

分步处理

步骤 1:确认 Redis 服务进程是否运行

执行 systemctl status redis 查看服务当前状态。若显示 inactive (dead) 或未识别服务名,运行 ps aux | grep redis 确认是否存在 redis-server 进程。若无进程,使用 redis-server `--daemonize` yes 启动守护进程模式,或运行 sudo systemctl start redis 设置开机自启。

步骤 2:验证 Redis 是否监听目标地址与端口

检查配置文件中 bind 指令。若仅存在 bind 127.0.0.1,则 Redis 只接受本地回环连接;远程连接需改为 bind 0.0.0.0 或显式列出客户端所在网段 IP。确认 port 值为 6379,并确保该端口未被其他程序占用。运行 ss -tlnp | grep :6379,观察输出中 LISTEN 状态对应的 IP 是否包含 0.0.0.0:6379 或具体对外 IP。

步骤 3:检查防火墙及网络策略限制

操作系统防火墙或云平台安全组可能拦截入站连接请求。在 Redis 所在服务器上执行 sudo ufw status (Ubuntu) 或 sudo firewall-cmd `--list-all` (CentOS/RHEL) 查看当前规则。若 6379 端口未开放,添加放行规则。若 Redis 部署于云服务器,登录控制台检查对应实例的安全组入方向规则。

步骤 4:核对 Celery 配置中的 broker_url 是否可达

确认 CELERY_BROKER_URL 值中主机名是否为容器内可解析地址。Docker Compose 中应使用服务名 (如 redis://redis:6379/0),而非 localhost 或 127.0.0.1。若密码含@、/等字符,必须进行 URL 编码。确认数据库编号是否存在,Redis 默认启用 db 0,若 URL 末尾缺失/0,部分 Kombu 版本会静默失败。

步骤 5:排查 Docker 环境中的网络隔离问题

进入 Celery Worker 容器内部,尝试连接 Redis。若 redis-cli -h redis -p 6379 ping 成功但使用宿主机 IP 失败,说明应统一使用 Docker Compose 定义的服务名作为 broker host。在 docker-compose.yml 中为 Redis 服务添加健康检查,确保其就绪后再启动 Worker 依赖服务。

怎么验证是否生效

运行 celery -A your_project_name worker `--loglevel`=info,观察输出里是否出现 Ready 和已注册的 task 名。如果报 ConnectionRefusedError,说明 broker 地址或端口不对。查看 Celery Worker 启动日志,确认无 Connection refused 或 NOAUTH 错误。使用 redis-cli ping 命令检查连接状态,若返回 PONG,说明 Redis 服务已运行且可响应。

Celery 连接 Redis 报 Connection refused,在 Django 项目里怎么解决?

常见坑

1. 密码中包含特殊字符 (如@,/,:),必须进行 URL 编码,否则会导致连接字符串解析错误。

2. 在 settings.py 中配置 Broker URL 时,严禁硬编码明文密码,避免敏感信息泄露至版本控制系统,建议通过环境变量注入敏感信息。

3. Docker 环境下 localhost 语义错位,Celery Worker 容器内无法通过 localhost 访问宿主机 Redis,需使用宿主 IP 或 Docker 服务名。

4. Redis 开启了密码验证但连接串未提供密码,或密码错误,会报 NOAUTH Authentication required 而非 Connection refused,但需一并排查。

常见问题

Celery Worker 启动成功但任务不执行怎么办?

绝大多数情况不是代码写错了,而是 celery worker 进程根本没启动,或者没连上正确的 broker。确认方法:运行 celery -A your_project_name worker `--loglevel`=info,观察输出里是否出现 Ready 和已注册的 task 名。

远程连接 Redis 一直报 Connection refused 如何解决?

首先确认 Redis 服务是否正常运行,可通过 redis-cli ping 命令检查连接状态。其次,核实 Redis 监听的 IP 和端口是否与 Celery 配置一致,默认情况下 Redis 使用 127.0.0.1:6379。此外,检查防火墙设置,确保 Redis 端口未被阻拦。

参考来源

1. Celery 连接 Django 项目报 Redis Connection Error 如何排查?

2. Celery -- kombu.exceptions.OperationalError: [Errno 61] Connection refused

3. Celery 连接 Redis 时,出现"Connection refused"错误如何解决?

4. 如何在 Python Django 中集成 Celery 处理耗时的异步后台任务?

5. Celery Worker 报 Connection refused 是 Broker 挂了吗?

6. Django 与 Celery 集成中的常见问题及解决方案-CSDN 博客

7. Redis 连接被拒绝 (Connection refused) 问题完整解决指南

8. Redis ConnectionRefusedError 连接被拒如何处理

9. 解决 Redis 远程连接"Connection refused"的完整排查与解决方案