我已经更改了标题“为什么第二个客户端无法访问该页面,直到第一个呼叫完成?”到“为什么来自同一IP的第二个客户端有一个显示页面前20秒超时?“。 所以在所有修改之前推理都不一样。
这里有2个网址:
/home
和/sleep
。
/home
显示主页
/sleep
睡10秒
我有2个客户:
客户1 :/sleep
- >等待10秒
客户端1 :/sleep
,客户端2 :/home
- > 客户端1 等待10秒,客户端2 即时加载页面。
客户端1 :/sleep
,客户端2 :/sleep
- > 客户端1 等待10秒,客户端2 等待 20 秒
为什么?我怎么能躲避这个?
如果此页面已被其他人调用,我想展示一些特别的内容。
这是我的代码:
$fileHandler = fopen('process.lock', 'w');
$hasLock = flock($fileHandler, LOCK_EX | LOCK_NB);
if (!$hasLock) {
return('already running'); // it never goes here.
}
for ($i = 0; $i < 10; ++$i) {
echo nl2br("$i" . PHP_EOL);
ob_flush();
flush();
sleep(1);
}
flock($fileHandler, LOCK_UN);
fclose($fileHandler);
多么巧合。实际上,它在20秒的等待时间内返回“已经运行”。这意味着如果我在for
中有一个无限循环,我会在客户端2 上“已经运行”但是超时为20秒。
我只是想知道它是什么超时。
我已经做了进一步的测试,证明它来自Apache或PHP配置,而不是我使用的功能:
/sleep
上的客户端1 :
public function sleep() {
// this is the endpoint of http://127.0.0.1/sleep
sleep(300);
}
然后我编辑此文件,以便客户端2 对该功能进行调用:
public function sleep() {
// this is the endpoint of http://127.0.0.1/sleep
die('hello');
}
如果我从5秒间隔(对文件进行更改的时间)运行我的两个客户端,则第二个客户端仍会等待20秒,然后才能打印hello
。
客户1 :127.0.0.1/sleep
- &gt;等待10秒
客户端2 :192.168.0.10/sleep
- &gt;等待10秒没有延迟
我的结论是问题来自同一IP的请求。为什么?
答案 0 :(得分:2)
根据PHP documentation,windows performs Mandatory locking flock()
。
这意味着系统会在文件操作(包括fopen)上检查锁定。
在Linux上,它会执行建议性锁定,要求所有试图通过调用flock()
来获取锁定的访问该文件的进程合作。
Windows变体允许您锁定一次并阻止所有其他程序,包括那些不了解您的代码的程序。
您的第二个客户端在fopen()
电话上阻止等待锁定释放。
编辑:我确实意识到我实际上没有回答你的第一个问题:如何避免这种情况。一个简单的解决方法是将代码移动到Linux服务器,如果有可能的话。否则,我建议你搜索如何在Windows上进行咨询锁定。