我在 jquery 中有以下查询。它正在读取使用 Nginx 长轮询模块设置的 Nginx 订阅/发布对的“发布”地址。
function requestNextBroadcast() {
// never stops - every reply triggers next.
// and silent errors restart via long timeout.
getxhr = $.ajax({
url: "/activity",
// dataType: 'json',
data: "id="+channel,
timeout: 46000, // must be longer than max heartbeat to only trigger after silent error.
error: function(jqXHR, textStatus, errorThrown) {
alert("Background failed "+textStatus); // should never happen
getxhr.abort();
requestNextBroadcast(); // try again
},
success: function(reply, textStatus, jqXHR) {
handleRequest(reply); // this is the normal result.
requestNextBroadcast();
}
});
}
该代码是聊天室的一部分。每条发送的消息都会以空 rply(200/OK)回复进行回复,但数据会被发布。这是数据返回时读取订阅地址的代码。
使用超时,聊天室中的所有人员每 30 到 40 秒发送一条简单消息,即使他们没有键入任何内容,因此此代码有大量数据可供读取 - 每 40 秒至少 2 条甚至可能更多消息。
该代码在 EI 和 Firefox 中 100% 坚如磐石。但在 Chrome 中读取大约 5 次失败。
当 Chrome 失败时,会出现 46 秒超时。
日志显示任一时间有一个未完成的 /activity 网络请求。
我已经爬行这段代码三天了,尝试各种想法。每次 IE 和 Firefox 工作正常,而 Chrome 却失败。
我看到的一个建议是使调用同步 - 但这显然是不可能的,因为它会锁定用户界面太长时间。
编辑 - 我有部分解决方案:代码现在是这样的
function requestNextBroadcast() {
// never stops - every reply triggers next.
// and silent errors restart via long timeout.
getxhr = jQuery.ajax({
url: "/activity",
// dataType: 'json',
data: "id="+channel,
timeout: <?php echo $delay; ?>,
error: function(jqXHR, textStatus, errorThrown) {
window.status="GET error "+textStatus;
setTimeout(requestNextBroadcast,20); // try again
},
success: function(reply, textStatus, jqXHR) {
handleRequest(reply); // this is the normal result.
setTimeout(requestNextBroadcast,20);
}
});
}
结果有时回复会延迟,直到 $delay (15000) 发生,然后排队的消息到达得太快而无法跟上。我无法使用这种新安排让它丢弃消息(仅在网络优化关闭的情况下进行测试)。
我非常怀疑延迟是由于网络问题造成的 - 所有机器都是我一台真机中的虚拟机,并且我的本地 LAN 没有其他用户。
编辑 2(英国夏令时星期五 2:30) - 更改代码以使用承诺 - 并且操作的 POST 开始显示相同的症状,但接收端开始正常工作! (???!!!???)。
这是 POST 例程 - 它正在处理一系列请求,以确保一次只有一个请求未完成。
function issuePostNow() {
// reset heartbeat to dropout to send setTyping(false) in 30 to 40 seconds.
clearTimeout(dropoutat);
dropoutat = setTimeout(function() {sendTyping(false);},
30000 + 10000*Math.random());
// and do send
var url = "handlechat.php?";
if (postQueue.length > 0) {
postData = postQueue[0];
var postxhr = jQuery.ajax({
type: 'POST',
url: url,
data: postData,
timeout: 5000
})
postxhr.done(function(txt){
postQueue.shift(); // remove this task
if ((txt != null) && (txt.length > 0)) {
alert("Error: unexpected post reply of: "+txt)
}
issuePostNow();
});
postxhr.fail(function(){
alert(window.status="POST error "+postxhr.statusText);
issuePostNow();
});
}
}
大约八分之一的操作对handlechat.php 的调用将超时并出现警报。一旦警报被确定,所有排队的消息都会到达。
我还注意到,handlechat 调用在写入其他人会看到的消息之前就停止了。我想知道这是否可能是 php 对会话数据的一些奇怪处理。我知道它会仔细地对调用进行排队,以便会话数据不会损坏,因此我一直小心地使用不同的浏览器或不同的机器。只有 2 个 php 工作线程,但是 php 不用于处理 /activity 或提供静态内容。
我还认为可能是 nginx 工作人员或 php 处理器短缺,所以我提出了这些问题。现在,让事情失败变得更加困难——但仍有可能。我的猜测是 /activity 调用现在失败率为 30 次,并且根本不会丢弃消息。
感谢大家的意见。
调查结果摘要。
1) 这是 Chrome 中的一个错误,该错误已经存在于代码中一段时间了。
2) 幸运的是,该错误可以显示为未发送的 POST,并且当超时时,Chrome 会处于重复 POST 将成功的状态。
3) 用于存储$.ajax()返回的变量可以是本地的或全局的。新的(承诺)和旧的格式调用都会触发该错误。
4)我还没有找到解决办法或避免该错误的方法。
Ian