You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Django+Celery+Channels时遭遇filedescriptor out of range in select()错误

解决方案:filedescriptor out of range in select() 错误排查与修复

这个问题我在维护类似的Django+Celery+Channels项目时也碰到过,核心原因是Python 3.6默认使用的SelectSelector依赖系统select调用,而select只能处理数值小于1024的文件描述符(FD)。当Celery worker长时间运行积累过多FD,或者async_to_sync处理异步上下文时FD未正确回收,就会触发这个偶发错误。结合你的环境,给你几个可行的解决办法:

1. 切换到无FD限制的选择器(推荐)

直接替换asyncio的默认选择器为PollSelector或EpollSelector(Linux专属,性能更好),突破1024的FD限制。

在Celery worker的启动入口(比如celery.py或项目初始化文件)添加以下代码:

import asyncio
from selectors import PollSelector  # Linux下可以换成EpollSelector

# 设置事件循环策略并替换选择器
asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())
loop = asyncio.get_event_loop()
loop.set_selector(PollSelector())

这段代码要保证在Celery worker启动前执行,确保所有异步上下文都使用新的选择器。

2. 优化Celery Worker的资源回收

Celery worker长时间运行可能出现FD泄漏,通过配置让worker处理一定任务后自动重启,避免FD持续积累:
在你的Celery配置文件中添加:

app.conf.update(
    worker_max_tasks_per_child=1000,  # 每个worker处理1000个任务后自动重启
    worker_disable_rate_limits=True,  # 禁用不必要的速率限制,减少FD占用
)

根据业务量调整worker_max_tasks_per_child的数值,比如任务耗时短可以设为2000,耗时久则设为500。

3. 规范async_to_sync的使用方式

检查你调用async_to_sync的异步函数,确保所有IO资源(数据库连接、Redis连接、文件句柄等)都被正确关闭。同时避免在Celery任务中手动创建事件循环——async_to_sync会自动处理事件循环的创建与销毁,手动创建反而可能导致FD泄漏。

错误示例(要避免):

# 不要在Celery任务里手动创建循环
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
async_to_sync(...)()

4. 升级Python版本(长远根治方案)

Python 3.7及以上版本默认使用PollSelector(跨平台)或EpollSelector(Linux),彻底移除了select的1024 FD限制。如果业务允许,升级到Python 3.8+不仅能解决这个问题,还能获得更好的性能和异步特性支持。

验证方法

修改配置后,你可以用lsof -p <worker_pid>命令查看Celery worker进程的FD数量,确认是否超过1024;同时观察业务运行,看错误是否不再触发。

内容的提问来源于stack exchange,提问作者hardik24

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:27:39