我在我的网站上有一个简单的长轮询请求,以检查是否有任何新通知可用于用户。就请求而言,一切似乎都可以完美地工作。仅在更新数据库(并且已为该特定用户创建通知)后,该请求才得到满足,然后立即发出新请求。
甚至更陌生的是,如果我访问我的localhost
个站点中的另一个(我的长期民意调查位于MAMP虚拟主机站点www.example.com
上),它们没有问题,我仍然可以使用它们好像什么都没发生-尽管它们在技术上在同一服务器上。
这是我在客户端(longpoll.js
)所拥有的:
window._Notification = {
listen: function(){
/* this is not jQuery's Ajax, if you're going to comment any suggestions,
* please ensure you comment based on regular XMLHttpRequest's and avoid
* using any suggestions that use jQuery */
xhr({
url: "check_notifs.php",
dataType: "json",
success: function(res){
/* this will log the correct response as soon as the server is
* updated */
console.log(res);
_Notification.listen();
}
});
}, init: function(){
this.listen();
}
}
/* after page load */
_Notification.init();
这就是我在服务器端(check_notifs.php
)所拥有的:
header("Content-type: application/json;charset=utf-8", false);
if(/* user is logged in */){
$_CHECKED = $user->get("last_checked");
/* update the last time they checked their notifications */
$_TIMESTAMP = time();
$user->update("last_checked", $_TIMESTAMP);
/* give the server a temporary break */
sleep(1);
/* here I am endlessly looping until the conditions are met, sleeping every
* iteration to reduce server stress */
$_PDO = new PDO('...', '...', '...');
while(true){
$query = $_PDO->prepare("SELECT COUNT(*) as total FROM table WHERE timestamp > :unix");
if($query->execute([":unix" => $_CHECKED])){
if($query->rowCount()){
/* check if the database has updated and if it has, break out of
* the while loop */
$total = $query->fetchAll(PDO::FETCH_OBJ)[0]->total;
if($total > 0){
echo json_encode(["total" => $total]);
break;
}
/* if the database hasn't updated, sleep the script for one second,
* then check if it has updated again */
sleep(1);
continue;
}
}
}
}
/* for good measure */
exit;
我已经阅读了有关 NodeJS 以及建议用于长期轮询的各种其他框架的信息,但不幸的是,它们目前对我来说是遥不可及的,因此我不得不使用 PHP < / strong>。我还环顾四周,看看Apache配置中的任何内容是否都可以解决我的问题,但是我只遇到了How do you increase the max number of concurrent connections in Apache?,考虑到我仍然可以使用我的内容,提及的内容似乎并不是问题所在相同服务器上的其他localhost
网站。
我对如何解决此问题感到非常困惑,因此,我们非常感谢所有帮助,
干嘛。
答案 0 :(得分:1)
实际情况是php正在等待此脚本结束(锁定)以将下一个请求提供给同一文件。
- 某处有一些锁-例如,如果两个请求来自同一客户端,而您正在使用,则会发生这种情况 PHP中基于文件的会话:执行脚本时, 会话被“锁定”,这意味着服务器/客户端将不得不等待 直到第一个请求完成(并且文件已解锁) 使用该文件为第二个用户打开会话。
- 请求来自相同的客户端和相同的浏览器;在这种情况下,即使存在 没有任何服务器端会产生这种行为。
- MaxClients当前活动的进程不止这些-之前请参阅Apache手册中的报价。
实际上某处有某种锁。您需要检查正在发生什么锁定。也许while($getwpi = $getwpicon->fetch_assoc()){
$year = date('Y', strtotime($getwpi['datum']));
$getwpi['datum'] = $year; // update your field
$wpi[] = $getwpi; // add to the result array
}
拥有锁,您必须在$_PDO
之前将其关闭,以保持解锁状态,直到发出下一个请求为止。
您可以尝试举起sleep(1)
和/或申请this answer
执行
MaxClients
(或cakephp中的相应功能)以在ajax端点的开头关闭会话。