
Laravel 开发环境下使用 php artisan serve 执行耗时 Shell 命令(如 FFmpeg 视频处理)会阻塞整个应用,导致其他请求无法响应;根本原因在于 PHP 内置开发服务器的单进程、单线程特性,而非 Session 锁问题。
laravel 开发环境下使用 `php artisan serve` 执行耗时 shell 命令(如 ffmpeg 视频处理)会阻塞整个应用,导致其他请求无法响应;根本原因在于 php 内置开发服务器的单进程、单线程特性,而非 session 锁问题。
在构建视频编辑类应用时,常需通过 AJAX 触发后端执行长时间运行的 FFmpeg 命令(例如转码、合并等),并期望:
✅ 用户页面可异步轮询或接收完成通知;
✅ 即使用户关闭浏览器,任务仍后台持续运行;
❌ 但实际中发现:所有 /localhost:8000 下的页面全部卡死,无法加载——这并非代码逻辑错误,而是开发服务器架构限制所致。
? 根本原因:php artisan serve 的局限性
Laravel 自带的 php artisan serve 基于 PHP 内置 Web 服务器(php -S),其本质是单进程、阻塞式、无并发能力的简易服务器,仅适用于本地开发调试。当一个请求(如调用 shell_exec('ffmpeg ...'))长期占用 PHP 进程时,该进程无法响应任何新请求,导致整个站点“冻结”。
⚠️ 注意:这不是 Session 锁导致的问题(session()->save() 或 session_write_close() 在此场景下无效),因为阻塞发生在进程层面,而非会话写入阶段。
✅ 正确解决方案:切换至生产级 Web 服务器
将开发环境迁移到 Apache 或 Nginx + PHP-FPM 组合,即可彻底解决并发阻塞问题:
-
Apache 示例配置(.htaccess 或 vhost):
<VirtualHost *:80> ServerName localhost DocumentRoot "/path/to/your/laravel/public" <Directory "/path/to/your/laravel/public"> AllowOverride All Require all granted </Directory> </VirtualHost> - 启动 Apache 后,直接访问
http://localhost(而非http://localhost:8000),此时每个 HTTP 请求由独立的 PHP-FPM 工作进程处理,FFmpeg 任务不再阻塞其他页面。
? 补充最佳实践(提升健壮性)
即使切换服务器,仍建议优化任务执行方式:
- 使用队列系统(如 Laravel Horizon + Redis)异步处理 FFmpeg 任务,避免同步阻塞请求生命周期;
- 示例(触发任务):
// 在控制器中 ProcessVideoJob::dispatch($videoId)->onQueue('videos'); return response()->json(['status' => 'processing', 'job_id' => $job->id]); - 配合数据库状态字段或 Redis 键记录任务进度,前端通过 AJAX 轮询
/api/video/status?id=xxx获取结果; - 确保
shell_exec或proc_open调用时重定向输出并脱离父进程(如exec("ffmpeg ... > /dev/null 2>&1 &")),防止请求超时中断子进程。
? 总结
不要在 php artisan serve 下测试长耗时 Shell 操作——它不是生产环境的模拟器,而是功能受限的调试工具。真实并发能力依赖于 Apache/Nginx + PHP-FPM 架构。迁移后,无需修改 Session 处理逻辑,即可天然支持多请求并行、后台任务持久化与用户体验解耦。


















