PHP后端长时Ajax请求下,如何发起新的服务器请求?
解决方案
你的问题核心是PHP会话锁机制导致的请求阻塞:同一个用户会话(由PHPSESSID标识)下,所有请求会串行执行——第一个长请求拿着session锁不放,后续请求必须等锁释放才能处理。下面是几种不依赖CronJob的直接解决方案:
1. 提前释放Session锁
只要长请求中不需要再读写session,就立刻调用session_write_close()释放锁,这样同会话的其他请求就能正常处理。
<?php session_start(); // 先完成所有需要操作session的逻辑(比如记录任务ID、用户身份) $_SESSION['long_task_id'] = uniqid('longtask_'); // 立刻释放session锁,让其他请求可以正常使用session session_write_close(); // 接下来执行耗时1-30分钟的业务逻辑 // 示例:模拟长时间操作 sleep(60); // ... 你的实际代码 ?>
2. 无会话模式处理长请求
如果长请求完全不需要依赖session,直接跳过session_start(),或者在请求开头就关闭会话(如果框架自动启动了session),彻底避免锁竞争。
<?php // 若框架已自动启动session,直接关闭释放锁 session_write_close(); // 执行耗时逻辑,全程不占用session锁 // ... ?>
3. 用fastcgi_finish_request()实现异步响应(FPM环境适用)
这个方法能让前端快速收到响应,同时后端在后台继续执行耗时任务,既不阻塞后续请求,也不用依赖CronJob。
<?php session_start(); $_SESSION['task_status'] = 'running'; session_write_close(); // 先释放锁,避免阻塞其他请求 // 先给前端返回响应,告知任务已接收 echo json_encode(['status' => 'accepted', 'task_id' => 'xxx']); // 结束与客户端的连接,后端继续执行任务 fastcgi_finish_request(); // 后台执行耗时1-30分钟的逻辑 sleep(1800); // 模拟30分钟操作 // 可以将任务状态更新到数据库/缓存,供后续查询 // ... ?>
这几个方案都能直接解决你的问题,其中提前释放session锁是最通用的方案,几乎适配所有PHP运行环境。
内容的提问来源于stack exchange,提问作者Web Star
相关产品推荐
相关产品推荐

