为何相同URL请求无法同时执行?PHP并发请求阻塞问题排查
PHP并发请求延迟的原因及解决办法
一、为什么会出现请求排队延迟?
1. PHP会话锁是核心问题
PHP默认用文件存储会话数据,只要请求触发了会话初始化(哪怕你没写session_start(),很多框架会自动启动),PHP就会给会话文件加排他锁。这个锁会一直持有到脚本结束,期间所有同会话的请求都得等着。
你的第一个请求执行sleep(10)时,锁没释放,第二个请求只能等10秒后第一个脚本跑完才能启动;第二个又sleep10秒,第三个继续等,就形成了排队延迟。
2. 浏览器并发限制导致第四个请求和第三个同时启动
现代浏览器对同一域名的并发请求数有默认限制(一般是2-6个)。前两个请求在队列里排队执行,等前两个处理完,浏览器会同时发起第三、第四个请求,所以它们的启动时间几乎一致。
二、怎么让请求同时启动?
1. 尽早释放会话锁
如果你的代码不需要全程用会话,拿到需要的会话数据后立刻调用session_write_close()释放锁,后续请求就能直接执行,不用等脚本结束。修改后的代码示例:
// 如果需要会话数据,先在这里读取 // 立即释放会话锁 session_write_close(); echo SystemService::getCurrentTime(); sleep(10); echo '------------2----' . SystemService::getCurrentTime(); die;
如果完全不用会话,直接禁用:
- 在脚本开头加
if (session_status() === PHP_SESSION_ACTIVE) session_destroy(); - 或者在PHP配置里关闭自动会话启动(
session.auto_start = 0),确保脚本不主动启动会话。
2. 换用无锁的会话存储
如果必须用会话,把会话存储从文件换成Redis、Memcached这类支持并发的引擎,它们不会产生文件锁阻塞。比如配置PHP的session.save_handler = redis,并设置好Redis连接参数。
3. 测试时调整浏览器并发(仅临时用)
浏览器的并发限制是安全机制,不建议日常修改,但本地测试时可以通过浏览器设置临时提高并发数,不过核心解决办法还是处理后端的会话锁问题。
验证效果
修改后再同时发起多个请求,所有请求的第一个时间戳会基本一致,不会再出现排队延迟。
内容的提问来源于stack exchange,提问作者Ahmet Rasim
相关产品推荐
相关产品推荐

