ASP.NET Core在Azure运行ffmpeg.exe并发编码崩溃最佳实践咨询
现有实现的问题
你的初步判断有误:Windows环境下多进程同时调用同路径下的ffmpeg.exe本身不会产生文件抢占冲突,exe文件在运行时是只读映射到进程内存空间的,多个进程可以同时加载同一个可执行文件运行,不存在锁exe导致崩溃的情况。
你现在并发场景下崩溃的核心原因是架构设计缺陷,常见的触发点包括:
- 没有给每个编码任务分配独立工作目录:所有并发任务共用同一路径读写临时文件、输出文件,出现文件锁冲突、临时文件互相覆盖,直接导致ffmpeg进程异常退出
- 没有做资源管控:ffmpeg编码是CPU、内存、磁盘IO密集型任务,你没有限制并行的ffmpeg进程数量,当并发任务数超过服务器硬件承载上限时,会出现内存溢出、CPU占满的情况,系统会强制杀掉占资源高的进程,直接把和ffmpeg跑在一起的API服务带崩
- 编码逻辑和API服务强耦合:你把耗资源的编码任务直接放在API请求处理链路里同步执行,ffmpeg一旦占满服务器资源,API服务就没有多余资源响应用户请求,直接出现服务崩溃、超时
- 没有子进程兜底逻辑:启动ffmpeg子进程时没有设置执行超时、没有捕获进程错误输出、没有做异常退出的资源回收,单个ffmpeg进程因为源文件损坏、参数错误等原因异常时,很容易产生僵尸进程、句柄泄漏,累积到一定程度就会拖垮整个服务。你当前把ffmpeg放在
C:\home\site\wwwroot\ffmpeg路径,说明你大概率用Azure App Service作为服务宿主,App Service本身是为短平快Web请求设计的沙箱环境,对长时间高CPU占用的进程有默认回收限制,本身就不适合跑视频编码这类重计算任务。
Azure平台使用FFmpeg做视频编码的最佳实践
- 架构上做API服务和编码任务解耦
不要在API请求处理链路里同步执行编码逻辑。API收到用户上传的视频后,只做基础的文件格式、大小校验,把编码任务信息写入消息队列后立刻给用户返回任务受理响应,编码逻辑由独立的后台计算节点拉取队列消息异步执行,就算编码节点崩溃也不会影响API服务的可用性。队列可以选Azure服务总线或者队列存储,不需要额外复杂组件。 - 选适配的计算服务跑编码任务
不要在Azure App Service里跑长时编码任务,根据业务规模选对应的计算服务:- 中小规模场景选Azure容器应用:把ffmpeg和编码逻辑打包成容器镜像,配置单实例的CPU、内存配额,支持基于队列长度的自动扩缩容,任务跑完自动回收实例,按实际资源使用量计费,运维成本极低
- 大规模批量编码场景选Azure Batch:这是专门为并行高性能计算任务设计的服务,可以自动调度多台虚拟机并行处理编码任务,内置任务重试、优先级调度、节点自动修复能力,适合每天有大量编码需求的场景
- 如果要用Azure Functions承载编码逻辑,不要选消费版计划——消费版函数最长执行时间只有10分钟,超时会被强制终止,必须选高级版或者专用计划,且配置足够长的函数超时时间
- 做好任务级别的隔离
每个并发编码任务必须分配全局唯一的临时工作目录,所有编码中间文件、日志、临时输出都写到这个专属目录下,绝对不能让多个任务共用同一个临时路径,任务执行完成(不管成功失败)后立刻清理该目录释放磁盘空间。启动ffmpeg进程时显式指定进程工作目录为该任务的专属目录,把标准输出、错误输出重定向到该目录下的日志文件,避免多进程输出流互相干扰。 - 严格管控并发数
根据计算节点的CPU核心数配置单节点最大并行编码数,一般1个物理核心同时跑1-2个编码任务就达到性能瓶颈,不要无限制启动ffmpeg进程。如果用支持自动扩缩容的服务,配置队列长度触发的扩缩容规则:待处理任务积压时自动增加计算节点,任务清空后自动缩容到最小实例数,平衡性能和成本。 - 存储层做性能适配
上传的源视频、编码完成的成品视频统一存到Azure Blob存储,不要存在计算节点的本地磁盘或者应用服务的共享磁盘里。编码任务启动时,先把源视频从Blob下载到计算节点的本地临时高性能盘,编码完成后再把成品回传到Blob存储,不要直接通过网络共享路径读写文件做编码,避免网络抖动导致编码失败。 - 完善异常兜底逻辑
每个ffmpeg进程启动后要监控退出码,捕获进程的错误输出,单任务失败时做最多2-3次指数退避重试,重试仍然失败就标记任务为失败状态,及时回收进程句柄、删除临时文件,避免僵尸进程、无效文件长期占用资源。给每个ffmpeg进程设置合理的执行超时阈值(比如根据视频时长按比例设置最长编码时间),超时后直接强制终止进程,避免异常任务长期占着资源不释放。
内容的提问来源于stack exchange,提问作者Gaetano Lenoci
相关产品推荐
相关产品推荐

