【发布时间】:2019-05-01 15:25:10
【问题描述】:
我在我的网站上有一个简单的长轮询请求,以检查是否有任何新通知可供用户使用。就请求而言,一切似乎都完美无缺。仅在更新数据库(并且已为该特定用户创建通知)后才满足请求,然后立即发送新请求。
问题
我注意到的是,当请求正在等待来自数据库的响应时(长轮询应该),对服务器的所有其他请求都会也挂起 - 无论是媒体文件,AJAX 请求甚至新页面加载。这意味着对服务器的 所有 请求将挂起,直到我关闭浏览器并重新打开它。
更奇怪的是,如果我访问我的另一个 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。我也环顾四周,看看 Apache 配置中是否有任何东西可以解决我的问题,但我只遇到了How do you increase the max number of concurrent connections in Apache?,考虑到我仍然可以使用我的其他 @ 同一服务器上的 987654328@ 网站。
我真的很困惑如何解决这个问题,所以感谢所有帮助,
干杯。
【问题讨论】:
-
您的问题很可能是
if($total > 0){,没有什么可能返回大于零的值,因此循环永远不会结束。 -
另外,你的查询在每个循环中总是相同的,所以循环在这里似乎没用,因为你总是会返回相同的数据。要更改此设置,请将
$_CHECKED、$_TIMESTAMP和$user->...内容移到 while 循环中。 -
@GetOffMyLawn 循环的重点是始终检查数据库是否正在更新:) 但这不是问题(长轮询本身工作正常),问题是它会挂起所有其他请求到那个 [virtualhost?] 服务器
-
请顶一下@Community
-
请将
$_PDO = new PDO('...', '...', '...');移到while循环之外,看看问题是否仍然存在。
标签: javascript php apache