1

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 状态,并且它们保持这种状态,直到我关闭服务器并再次备份。

感谢您花时间阅读所有这些内容,如果您需要更多信息来帮助我在此处隔离问题,请告诉我。在此期间,我将继续挖掘。

4

0 回答 0