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

使用django-eventstream遭遇Too many open files错误的解决求助

解决django-eventstream在RHEL7.4上的"too many open files"问题

我来帮你拆解这个问题:你遇到的too many open files本质是文件句柄泄漏,大内存服务器因为系统资源充足,不会主动回收闲置的文件句柄,导致累积到上限触发错误;而小内存笔记本因为资源紧张,操作系统会自动清理闲置句柄,所以没暴露这个问题。下面给你几个分层的解决方向:

一、临时缓解:提高系统文件句柄限制

这是最快的应急方案,先让服务能正常运行,再排查根本问题:

  • 临时生效(当前会话):执行ulimit -n 65535,把单个进程的最大文件句柄数调高到65535(默认可能只有1024或4096)
  • 永久生效:修改/etc/security/limits.conf,添加以下配置:
    * soft nofile 65535
    * hard nofile 65535
    root soft nofile 65535
    root hard nofile 65535
    
    然后重启系统,或者让用户重新登录后生效。同时调整系统全局的文件句柄上限:
    echo 1000000 > /proc/sys/fs/file-max
    
    永久保存的话,在/etc/sysctl.conf中添加fs.file-max = 1000000,再执行sysctl -p生效。

二、根本排查:定位django-eventstream的句柄泄漏

你的测试显示每次刷新页面都会新增线程和2000+文件句柄,说明连接关闭时没有正确清理资源:

  1. 升级django-eventstream到最新稳定版:检查官方是否有已知的线程/句柄泄漏bug,很多这类问题在新版本中会被修复。
  2. 追踪句柄持有情况:用lsof -p <你的Python进程PID> | grep .so查看具体是哪些动态库没有被关闭,然后用tracemalloc或objgraph工具追踪这些句柄的持有者,确认是django-eventstream本身的逻辑问题,还是依赖库的问题。
  3. 检查连接清理逻辑:django-eventstream在客户端断开连接(比如页面刷新)时,是否正确终止对应的线程并释放加载的动态库?可以查看它的源码中disconnect相关的处理函数,确认有没有遗漏资源释放的步骤。

三、优化服务器配置:减少不必要的线程创建

你用gunicorn生成uvicorn worker,或者用runserver都有问题,说明线程创建的逻辑可能来自django-eventstream本身,但可以通过服务器配置优化:

  • 调整gunicorn的worker/线程数:避免过多worker和线程导致句柄爆炸,比如用gunicorn --workers=4 --threads=2 your_project.asgi:application -k uvicorn.workers.UvicornWorker,根据服务器CPU核心数调整worker数量(一般是CPU核心数的2倍),线程数不要太高。
  • 切换到纯ASGI模式运行:django-eventstream是基于ASGI的,直接用uvicorn运行ASGI应用,而不是通过gunicorn包装,可能减少不必要的线程创建。比如执行uvicorn your_project.asgi:application --host 0.0.0.0 --port 8000。

四、针对RHEL7.4的系统特性优化

RHEL7.4的默认系统配置对大内存环境的资源回收不够积极,可以调整以下参数:

  • 开启文件句柄的自动回收:修改/proc/sys/vm/swappiness(如果不需要swap可以调低,但这里主要是让系统更积极回收闲置资源),或者调整/proc/sys/fs/inotify/max_user_watches(如果涉及文件监听的话)。
  • 检查SELinux设置:RHEL7.4的SELinux可能会限制进程的文件操作权限,导致句柄无法正常释放,可以临时关闭SELinux(setenforce 0)测试,如果问题消失,再调整SELinux的策略。

五、验证动态库加载问题

你提到每次线程都会加载大量.so文件,可能是Python线程没有共享已加载的动态库,导致每个线程都重复加载:

  • 设置Python环境变量PYTHONMALLOC=malloc,强制使用系统malloc而不是Python的内存分配器,可能改善动态库的共享情况。
  • 检查依赖的C扩展库:比如django-eventstream依赖的某些库在多线程环境下是否正确使用RTLD_GLOBAL标志加载动态库,确保线程间可以共享已加载的库文件句柄。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:24:01