tl;dr:jQuery 的 ajax 函数似乎不会关闭超时的 http 请求。因此,每个长轮询请求打开的每个套接字都不会关闭,并且由于打开的套接字数量,服务器最终会拒绝连接。 是否可以在这些连接超时后关闭它们,这样我就可以开始下一次长轮询,而不必担心无休止地打开 [并随后孤立] 连接?如果不是,我的长轮询方法哪里出错了?
注意:我意识到这可能是预期的行为,但我在跟踪所有活动部件并隔离我对问题的误解时做了一个噩梦。您可以提供的任何指导/说明将不胜感激。
我开发了一个简单的应用程序来演示使用 lighttpd、cppcms(一个 C++ Web 框架)和 jQuery 的基于推送的通知。客户端这样做:
function listen(){
$.ajax({
url: "/push_test",
type: "POST",
timeout: 3000, // 3 seconds
data: {
will_leak: true
},
success: function(r){
console.log("server responded: " r);
},
error: function(xhr, st, e){
console.log("push_test error");
console.dir(xhr);
console.log("status: " + st);
console.log("error: " + e);
},
complete: function(){
//listen();
}
});
}
然后服务器执行类似的操作(我在 python Flask 微框架中进行了类似的测试,结果与以下 cppcms 实现相同):
void push_test()
{
if(request().post("will_leak")){
std::this_thread::sleep_for(std::chrono::seconds(5)); // Note client timeout of 3 seconds.
}
response().set_plain_text_header();
response().out() << "If you see this on the client, we're all gucci";
// Hint: if will_leak was true, you never see the above message.
}
在ajax调用超时时检查Firefox开发者工具的network选项卡表明HTTP请求从未返回响应或状态码,但控制台在ajax调用的“错误”回调中显示超时失败。对 Chrome 的开发人员工具的网络选项卡进行的类似检查表明,当我们达到超时时,请求被“取消”。检查服务器上打开的套接字文件描述符表明已超时的套接字处于 CLOSE_WAIT 状态,并且它们保持这种状态,直到我关闭服务器并再次备份。
感谢您花时间阅读所有这些内容,如果您需要更多信息来帮助我在此处隔离问题,请告诉我。在此期间,我将继续挖掘。