php artisan serve启动的Laravel项目控制器执行批处理时全站卡住无法并发请求
问题诱因
- 核心原因:你使用的
php artisan serve启动的是PHP内置的轻量开发服务器,该服务仅用于本地开发测试场景,本身是单进程设计,同一时间只能处理1个请求,前序请求执行完成前不会响应任何后续请求。你的业务逻辑中单个请求需要阻塞6分钟等待批处理执行,自然会堵塞所有其他用户的访问请求。 - 附加影响:哪怕更换为多进程的Web服务,你当前在控制器中同步等待长耗时批处理返回的逻辑,也会持续占用Web工作进程,并发请求量稍高就会出现进程占满、站点无响应的问题。
解决方案
1. 更换多进程Web服务
立刻停止使用php artisan serve作为运行服务,根据你的运行场景选择对应方案:
- 生产环境Windows部署可以使用WAMP/XAMPP集成环境,采用Apache或者Nginx + PHP-FPM的多进程架构,默认支持同时处理多个请求,不会因为单个请求阻塞全站。
- 本地开发需要模拟多请求处理能力可以使用Laravel Octane,搭配RoadRunner运行(Windows环境无需WSL即可直接支持),可自定义启动多进程处理请求。
2. 优化长耗时任务处理逻辑
无论用哪种Web服务,都不建议在控制器中同步等待6分钟的批处理执行,建议改用Laravel队列架构解耦:
- 将执行bat批处理、处理返回结果的逻辑封装为独立的队列任务类,用户提交表单后直接将任务推入队列,立刻给用户返回「任务已提交,后台处理中」的响应,不会占用Web请求进程。
- 单独启动队列Worker进程处理长耗时任务,任务执行完毕后可通过站内通知、邮件等方式告知用户,也可在数据库中记录任务执行状态,给用户提供进度查询入口。
3. 特殊场景的临时兼容方案
如果确实需要在请求中触发批处理且无法改造为队列,可修改exec调用逻辑,让批处理后台异步运行,避免阻塞控制器:
// Windows环境下让bat后台运行,不阻塞当前请求,输出结果写入log文件 exec('start /B 你的批处理文件路径.bat > 输出日志路径.txt 2>&1');
调整后控制器无需等待批处理执行完成即可返回响应,后续可通过轮询日志文件的方式给用户同步执行结果。
内容的提问来源于stack exchange,提问作者lely
相关产品推荐
相关产品推荐

