Node.js处理高并发带文件POST请求 解决ffmpeg进程被杀死问题
问题根因
该问题核心是高并发场景下同时启动的ffmpeg进程过多,2核2G的服务器配置无法承载,导致内存/CPU占用超出系统阈值,进程被Linux内核的OOM Killer强制杀死,常规配置下同时跑超过5个ffmpeg进程就会有很高的触发概率。
解决方案
1. 新增任务队列,限制ffmpeg并发数
这是优先级最高的修复方案,禁止请求直接触发ffmpeg进程启动,通过队列控制同时运行的ffmpeg进程数,2核2G配置建议并发数设为2~3即可。Node.js可直接用p-queue或bull库实现队列:
import PQueue from 'p-queue'; // 固定ffmpeg最大并发数 const ffmpegQueue = new PQueue({ concurrency: 2 }); // 原有视频处理逻辑封装为独立函数 async function processVideo(filePath, processParams) { // 你的ffmpeg裁剪、封面生成、压缩逻辑 } // 接口接收请求后将任务推入队列 app.post('/video/upload', async (req, res) => { const uploadFile = req.file; // 业务允许的话优先用异步模式:直接返回任务ID,前端轮询/后端回调通知处理结果,避免请求超时 const taskId = generateTaskId(); ffmpegQueue.add(() => processVideo(uploadFile.path, req.body)) .then(async (processResult) => { // 上传到S3逻辑 // 更新任务状态 }) res.send({ code: 0, taskId }) })
如果必须用同步返回模式,队列长度超过阈值时直接返回系统繁忙提示,引导用户稍后重试,避免队列无限堆积。
2. 优化ffmpeg参数,降低单进程资源占用
- 新增
-threads 1参数,限制单个ffmpeg进程只用1个线程,避免单个进程占满全部CPU资源 - 视频压缩时用
-preset fast参数平衡编码速度和压缩率,不要用veryslow这类高消耗参数 - 生成封面时优先跳转到指定时间点再取帧,不要扫描全量视频,大幅降低执行耗时
参考优化后命令:
# 封面生成优化命令 ffmpeg -ss 00:00:01 -i input.mp4 -vframes 1 -q:v 2 cover.jpg # 视频压缩优化命令 ffmpeg -i input.mp4 -threads 1 -c:v libx264 -preset fast -crf 28 output_compressed.mp4
3. 系统层面适配优化
- 给ffmpeg进程设置更低的OOM优先级,避免被系统优先杀死:启动ffmpeg后拿到进程PID,执行
echo -1000 > /proc/<ffmpeg_pid>/oom_score_adj - 开启2G容量的swap分区,超出内存占用时优先用虚拟缓存,避免进程直接被杀:
sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
- 新增定时任务清理public目录的残留临时文件,避免存储占满触发系统异常。
4. 异常容错补充
- 给ffmpeg进程增加超时逻辑,超过10分钟未执行完成直接主动杀掉,避免僵尸进程占资源
- 捕获进程被杀异常后自动将任务推入队列重试,最多重试2次
- 新增系统资源监控,CPU/内存占用超过80%时暂时拒绝新的上传请求。
内容的提问来源于stack exchange,提问作者drimil gondaliya
相关产品推荐
相关产品推荐

