FastAPI多Worker模式下子进程莫名终止问题求助
问题描述
我部署了一个FastAPI服务,负责从数据库拉取约20GB的数据并做处理。环境配置如下:
- 依赖版本:
- fastapi==0.115.6
- fastapi-cli==0.0.5
- uvicorn==0.34.0
- 机器配置:8核64GB内存
现象:
- 单Worker启动(命令:
fastapi start src/api.py --port 3000):服务能正常完成全量数据拉取和处理,内存占用稳定在20-40GB。 - 多Worker启动(例如:
fastapi start src/api.py --port 3000 --workers 2):只要子进程内存占用达到4-5GB就会终止,无论Worker数量设为多少(>1)都出现相同问题。
已排查内容:
- 执行以下命令排查内核日志,未发现OOM或进程被SIGKILL的记录:
journalctl -k | grep -i "oom" journalctl | grep -E 'killed|SIGKILL' sudo dmesg | grep -i "killed process" - 通过htop确认子进程确实在内存到4-5GB时终止,且API内部无多处理逻辑,均为顺序执行,未使用异步特性。
排查与解决方案
1. 检查进程资源限制
系统层面的RLIMIT_AS(地址空间限制)可能被设置,导致多Worker模式下子进程内存被限制在4-5GB。可以通过代码验证:
import resource def print_memory_limit(): soft_limit, hard_limit = resource.getrlimit(resource.RLIMIT_AS) print(f"内存软限制: {soft_limit / (1024**3):.2f} GB, 硬限制: {hard_limit / (1024**3):.2f} GB") # 在API启动入口调用 print_memory_limit()
如果多Worker模式下软限制为4-5GB左右,说明是资源限制导致进程终止。解决办法:
- 启动服务前执行
ulimit -v unlimited(或设置足够大的值),再启动服务; - 若使用systemd管理服务,在service配置中添加
LimitAS=infinity。
2. 直接用Uvicorn启动服务
fastapi-cli的封装可能隐含了Worker配置问题,尝试跳过fastapi-cli,直接用Uvicorn命令启动,精准控制参数:
uvicorn src.api:app --port 3000 --workers 2 --worker-class uvicorn.workers.UvicornWorker --loop sync
指定同步循环和标准Worker类,避免fastapi-cli的默认配置干扰。
3. 捕获进程终止信号
子进程可能收到了SIGSEGV、SIGABRT等非OOM信号,添加信号捕获代码记录终止原因:
import signal import sys import traceback def signal_handler(signum, frame): print(f"收到信号: {signal.Signals(signum).name}") traceback.print_stack(frame) sys.exit(1) # 注册常见终止信号处理 signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGSEGV, signal_handler) signal.signal(signal.SIGABRT, signal_handler)
将这段代码放在API启动入口,子进程终止时会打印信号类型和调用栈,帮助定位问题。
4. 检查Python内存限制
部分环境可能设置了PYTHONMEMORYLIMIT环境变量限制Python进程内存,执行以下命令检查:
echo $PYTHONMEMORYLIMIT
如果有设置,取消该环境变量后重新启动服务。
5. 优化数据加载方式
即使单Worker能扛20GB内存,多Worker场景下建议改用流式加载数据,避免一次性全量拉取:
- 若使用SQLAlchemy,用
yield_per()分批获取数据; - 若使用原生数据库驱动,开启流式游标(如psycopg2的
name='server-side-cursor')。
内容的提问来源于stack exchange,提问作者Sriram R
相关产品推荐
相关产品推荐

