
Laravel 开发环境下使用 php artisan serve 执行长时间 Shell 命令(如 FFmpeg 视频处理)时,会因 PHP 内置服务器单进程特性导致整个站点响应冻结;切换至 Apache/Nginx 等生产级 Web 服务器即可根本解决该并发阻塞问题。
laravel 开发环境下使用 `php artisan serve` 执行长时间 shell 命令(如 ffmpeg 视频处理)时,会因 php 内置服务器单进程特性导致整个站点响应冻结;切换至 apache/nginx 等生产级 web 服务器即可根本解决该并发阻塞问题。
在构建 Laravel 视频编辑应用时,常需通过 AJAX 触发后端执行耗时的 FFmpeg 命令(例如转码、剪辑等,持续数分钟)。虽然可通过 shell_exec() 或 Process 类调用命令,并配合 session()->save() / session_write_close() 缓解会话阻塞,但在 php artisan serve 开发服务器下,这些优化均无法彻底解决问题——根本原因在于:PHP 内置服务器是单线程、单进程模型,同一时间仅能处理一个请求;当一个请求(如 /api/process-video)长时间占用 Worker 进程时,其他所有请求(如 /dashboard、/api/status)将被排队阻塞,表现为“整个 localhost:8000 站点卡死”。
✅ 正确解决方案:停止使用 php artisan serve,改用 Apache 或 Nginx 部署 Laravel 应用。
这类成熟 Web 服务器支持多进程/多线程模型(如 Apache 的 prefork 或 event MPM,Nginx 的异步非阻塞架构),可并行处理多个请求。即使某个 FFmpeg 进程运行 10 分钟,其他用户访问或轮询状态接口仍能即时响应。
? 同时建议配合以下最佳实践增强健壮性:
-
显式关闭会话写入(虽非根本解,但仍是良好习惯):
// 在控制器中,调用耗时命令前释放会话锁 request()->session()->save(); // Laravel 8+ // 或兼容写法 session_write_close(); $output = shell_exec('ffmpeg -i input.mp4 -c:v libx264 output.mp4 2>&1'); -
异步化处理(推荐进阶方案):
使用 Laravel 队列(如database或redis驱动)将 FFmpeg 任务推入后台,前端通过轮询/api/job-status/{id}获取进度,避免长连接阻塞:php artisan queue:work --daemon
并在队列任务中调用
Process::fromShellCommandline()安全执行命令。 -
守护进程与超时防护:
为防止 FFmpeg 意外挂起,添加超时与错误捕获:use Illuminate\Support\Facades\Process; try { Process::timeout(600)->run('ffmpeg -y -i input.mp4 -c:v libx264 output.mp4', function ($process) { // 实时日志或进度解析(需 FFmpeg 输出格式支持) }); } catch (ProcessTimedOutException $e) { Log::error('FFmpeg timeout', ['job_id' => $jobId]); }
⚠️ 注意事项:
-
php artisan serve仅用于开发调试,严禁用于生产或压力测试场景; - 即使切换至 Apache/Nginx,也应确保
max_execution_time和memory_limit设置合理(FFmpeg 内存消耗较大); - 若必须本地快速验证,可临时启用 PHP-FPM + Nginx(如 Laravel Valet 或 Docker 环境),而非依赖内置服务器。
综上,该问题本质是开发工具链选型不当所致。回归标准 Web 服务器架构,辅以 Laravel 队列与进程管理机制,即可实现高并发、高可靠性的视频处理服务。


















