我对ajax comet有一个问题-加载页面后,一切都很好,但当我尝试在同一主机上打开其他页面(一些菜单或链接)时,这个页面会在很长时间后加载(非常慢)。
服务器是Slackware 13.37 Apache/2.2.20 PHP 5.3.8,脚本是backend.PHP:
<?php
function my_abort_handler( ) {
write2file(connection_status() . ' SD Aborted!!!');
}
register_shutdown_function('my_abort_handler');
try {
error_reporting(0);
session_start();
if (!isUserLogedIn()) {
$return['message'] = "Login required";
$return['error'] = true;
echo json_encode($return);
exit();
}
if (empty($_SESSION['return'])) {
$_SESSION['return'] = false;
}
connectToDB();
while (!connection_aborted()) {
write2file(connection_status() . ' SD Aborted!!!');
$return = collectDataFromDB();
$d1 = array_diff_assoc($return, $_SESSION['return']);
$d2 = array_diff_assoc($return, $_SESSION['return']);
if ((!empty($d1)) || (!empty($d2))) {
$_SESSION['vote_return'] = $return;
echo json_encode($return);
flush();
ob_flush();
exit();
}
sleep(1);
}
} catch (Exception $e) {
$return['message'] = $e->getMessage();
$return['error'] = true;
echo json_encode($return);
}
在客户端:
var xhReq = false;
function runComet() {
xhReq = GetXmlHttpObject();
xhReq.open("GET",'backend.php',true);
xhReq.onreadystatechange=consoleinfo;
xhReq.send(null);
}
function consoleinfo() {
if (xhReq.readyState == 4) {
if (xhReq.status == 200) {
console.info(xhReq.responseText);
} else {
console.info("Error Status:" + xhReq.status);
}
runComet();
}
runComet();
Seteps:
- 打开页面并执行javascript,因此存在对backend.php的请求
- 监视日志文件-每1秒有一个新行
- 按下页面上的链接/菜单,浏览器开始加载下一页。在控制台(firebug或chrome控制台)中,我看到ajax请求被中止
- 监视日志文件-每隔1秒就会有新行,这样服务器上的连接就不会中止
- 打开http://localhost/server-status我可以看到状态为"W"的工作人员正在发送回复
- 等待一段时间(每次不同,但在大多数情况下大约30-60秒)连接关闭,因此在日志文件中我看到中止消息
- 加载下一页
我在每秒钟和刷新页面浏览器时创建了一个非常简单的案例-后端返回时间():-等待大约30-60秒,直到我在日志文件中看到中止消息或-realod页面,但在日志文件中没有中止。每个relod都会添加新的工作人员http://localhost/server-status日志文件中添加的行与worker相同。
我在CentOS 5.5服务器上尝试了一下,结果是一样的。我使用defautl apache配置(只添加一些虚拟主机并启用服务器状态)。
我认为配置有问题,但我不明白在哪里。你能帮我解决这个问题吗。
更新:我使用netstat来检查发生了什么。当请求处于活动状态时,netstat输出为:
tcp 0 0 127.0.0.1:35518 127.0.0.1:80 ESTABLISHED 2660/firefox off (0.00/0/0)
CCD_ 1后netstat输出为:
tcp 1 0 127.0.0.1:80 127.0.0.1:35518 CLOSE_WAIT 3174/httpd keepalive (7167.02/0/0)
因此在这种情况下,连接将保持活动7167秒,后台脚本将工作7167秒。这可能是操作系统配置的问题。
这里有两个问题:
第一:下一页加载缓慢-这是因为在每一页中我都使用session_start()
。如果我在backend.php中启动会话,会话将在脚本完成后关闭并保存(因为我从不编写并关闭它)。这就是下一页打开速度太慢的原因(下一页也使用session_start()
)。为了解决这个问题,我从backend.php中删除了session_start()
,但如果添加"session_write_close()",它也必须解决这个问题。
第二:backend.php不停止执行-这是因为我使用mod_php和php无法检测到浏览器断开连接/关闭。要检测浏览器断开连接,php脚本必须发送一些输出。在backedn.php中,我添加了要在每个while循环上执行的echo '0'; flush(); ob_flush();
。因此,backend.php将在每个周期输出"0",它将检测浏览器何时断开连接(打开其他页面或按下停止按钮)或关闭,并停止执行。在客户端,我替换了.replace(/^0*/, '');
,所以我删除了所有不必要的输出。
这解决了问题——现在,当浏览器试图打开其他页面,并且下一个页面(在此服务器上)按时打开时,后端脚本会停止执行。
我也遇到了同样的问题,但当页面像一样加载时,我在10秒钟后调用了我的comet ajax函数
$(function(){
setTimeout('updateFeed()',10000);
});
它的工作原理就像一个魅力