9

我刚刚读到一些浏览器会阻止 HTTP 轮询(我猜是通过限制请求的速率)......

来自https://github.com/sstrigler/JSJaC

注意:由于大多数现代浏览器的安全限制阻止 HTTP Polling 不再可用,此模块现在默认禁用。如果你想编译它使用'make polling'。

这可以解释我的一些 JavaScript 的一些不当行为(有时请求只是没有发送或重试,即使它们实际上是成功的)。但是我找不到有关详细信息的更多信息..

问题

  • 如果它是“每 x 秒的最大请求数 n”,x 和 n 的通常/默认设置是什么?
  • 有什么好的资源吗?
  • 有什么方法可以检测请求是否由于速率限制而被“延迟”或“拒绝”?

谢谢你的帮助...

斯特凡

4

6 回答 6

4

是的,据我所知,每个请求的默认池限制为 10,默认请求超时为 30 秒,但是可以控制超时和轮询限制,并且不同的浏览器实现不同的限制!

查看这个Google 实施

这是捕捉超时错误的一个很棒的实现!

您可以在这里找到 Firefox 的详细信息!

Internet Explorer 的细节是从 Windows 注册表内部控制的。

也看看这个问题

基本上,您控制的方式不是通过更改浏览器限制,而是通过遵守它们。因此,您应用了一种称为节流的技术。

将其视为创建函数的 FIFO/优先级队列。将 xhr 请求作为成员并在它们之间强制延迟的队列结构是 Xhr 轮询。例如,我正在使用 Jsonp 从位于另一个域的 node.js 服务器获取数据,当然由于浏览器的限制,我正在轮询。否则,我从服务器得到零响应,这仅仅是因为浏览器的限制。

我实际上正在为每个应该发送的请求做一个控制台日志,但并不是所有的请求都被记录下来。所以浏览器限制了它们。

我会更具体地帮助你。我的网站上有一个页面,该页面应该呈现数十甚至数百篇文章的视图。您可以使用很酷的水平滑块浏览它们。

滑块的当前值与当前的“页面”匹配。由于我每页只显示 5 篇文章,而且我无法完全加载数千篇文章“onload”而不会对性能产生严重影响,因此我加载了当前页面的文章。我通过向 Python 脚本发送跨域请求来从 MongoDB 获取它们。

该脚本应该返回一个包含五个对象的数组,其中包含我为“页面”构建 DOM 元素所需的所有详细信息。但是,有几个问题。

首先,滑块工作得非常快,因为它或多或少是一个值变化。即使有拖放功能、按键事件等,实际更改也需要几毫秒。但是,滑块的代码如下所示:

goog.events.listen(slider, goog.events.EventType.CHANGE, function() {
    myProject.Articles.page(slider.getValue());
}

slider.getValue() 方法返回一个带有当前页码的 int,所以基本上我必须从以下位置加载:

currentPage * articlesPerPage to (currentPage * articlesPerPage + 1) - 1

但是为了加载,我做了这样的事情:我有一个存储引擎(把它想象成一个数组):

  • 我检查内容是否已经存在
  • 如果是,则没有必要再发出请求,因此请继续从数组中获取 DOM 元素,并将已创建的 DOM 元素放在适当的位置。
  • 如果不是,那么我需要得到它,所以我需要发送我提到的那个请求,它看起来像(不考虑浏览器限制):

    JSONP.send({'action':'getMeSomeArticles','start':start,'length': itemsPerPage, function(callback){

    // 现在我只是快速解析回调以确保它是一致的 // 创建 DOM 元素,并填充客户端存储 // 并为用户更新视图。}}

问题来自您更改该滑块的速度。由于每个更改都应该触发一个请求(正常的 Xhr 请求也会发生同样的情况),所以您基本上跨越了所有浏览器的限制,所以如果没有限制,大多数请求都不会有“回调”。'callback' 是 JSONP 请求返回的 JS 代码(这更像是一个远程脚本包含而不是其他任何东西)。

所以我所做的是将请求推送到优先级队列,而不是 POLL,因为现在我不需要同时发送多个请求。如果队列为空,则执行最近添加的成员,每个人都很高兴。如果不是,则取消所有正在进行的未完成请求,仅执行最后一个请求。

现在,在我的特定情况下,我进行二进制搜索(0(log n))以查看存储引擎是否还没有先前请求的数据,这会告诉我先前的请求是否已完成。如果有,则将其从队列中删除并处理当前的,否则将触发新的。如此等等。

同样,为了速度考虑和讨厌的浏览器,如 Internet Explorer,我提前 3-4 步执行上述过程。所以我提前预加载了 20 页,直到一切都是客户端存储引擎。这样,每个限制都被成功处理。

冷却时间由滑过 20 页所需的最短时间覆盖,并且节流确保在任何给定时间不超过 1 个活动请求(向后兼容至 Internet Explorer 5)。

我写这一切的原因是为了给你一个例子,试图说明你不能总是直接从 FIFO 结构中强制延迟,因为你的调用可能需要变成用户看到的,而你并不完全想要用户等待 10-15 秒以呈现单个页面。

此外,始终尽量减少轮询和轮询的需要(同时触发 Ajax 事件,因为并非所有浏览器实际上都对它们做了好事)。例如,与其发送一个请求以获取内容并发送另一个请求以在您的应用指标中查看要跟踪的内容,不如在服务器级别执行尽可能多的任务!

当然,您可能希望正确地跟踪您的错误,因此您选择的库中的 Xhr 对象为 ajax 实现错误处理,并且因为您是一个了不起的开发人员,所以您想使用它们。

所以假设你有一个 try - catch 块 场景是这样的:一个 Ajax 调用已经完成,它应该返回一个 JSON,但是调用不知何故失败了。但是,您尝试解析 JSON 并使用它做任何您需要做的事情。所以

function onAjaxSuccess (ajaxResponse) {
    try {
        var yourObj = JSON.parse(ajaxRespose);
    } catch (err) {
    // Now I've actually seen this on a number of occasions, to log that an error occur
    // a lot of developers will attempt to send yet another ajax request to log the
    // failure of the previous one.
    // for these reasons, workers exist.
    myProject.worker.message('preferrably a pre-determined error code should go here');
    // Then only the worker should again throttle and poll the ajax requests that log the
    //specific error. 
};

};

虽然我已经看到各种实现尝试同时触发尽可能多的 Xhr 请求,直到遇到浏览器限制,然后在等待浏览器“冷却”时停止未触发的请求方面做得很好',我可以建议您考虑以下几点:

  • 速度对您的应用程序有多重要?
  • I/O 的可扩展性和密集程度如何?

如果第一个的答案是“非常”,而后者的答案是“OMFG 现代技术”,那么尽量优化你的代码和架构,这样你就不需要同时发送 10 个 Xhr 请求。此外,对于大型应用程序,多线程您的流程。实现这一点的 JavaScript 方法是使用工作者。或者你可以打电话给 ECMA 委员会,告诉他们将其设为默认值,然后将其发布在这里,以便我们其他 JS 开发人员可以享受 JS 中的原生多线程:)(他们怎么没想到这个?! ?!)

于 2012-10-16T19:41:48.763 回答
3

Stefan,下面的快速答案:

- 如果它是“每 x 秒的最大请求数 n”,x 和 n 的通常/默认设置是什么?这听起来更像是服务器限制。浏览器通常听起来像:-“相同主机名的最大请求数是 x”-“任何主机名的最大连接数是 y”

- 有什么好的资源吗? http://www.browserscope.org/?category=network(也可以将鼠标悬停在表头上以查看测量的内容) http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-连接

- 有什么方法可以检测请求是否由于速率限制而被“延迟”或“拒绝”?您可以查看“连接:关闭”的 http 标头以检测服务器限制,但我不知道 JavaScript 能够以一致的、独立于浏览器的方式从这么多浏览器中读取设置。(对于 Firefox,你可以阅读这个http://support.mozilla.org/en-US/questions/746848

希望这个快速回答有帮助吗?

于 2012-10-18T10:28:26.897 回答
2

我编写了一些带有长轮询的应用程序,一些使用 C++ 后端和我自己的网络服务器,还有一个使用 PHP 后端和 Apache2。

我的长轮询超时是 4..10 秒。当发生某些事情或 4..10 秒过去时,我的服务器返回一个空响应。然后客户端立即启动另一个 AJAX 请求。我发现当我从以前的 AJAX 处理程序启动 AJAX 调用时,某些浏览器会挂起,所以我使用 setTimeout() 和一个小值来启动下一个 AJAX 请求。

当客户端发生某些事情,应该发送到服务器时,我使用另一个 AJAX 请求,但这是单向的:服务器不发送任何响应,客户端不处理任何内容。操作的结果(如果有)将在长轮询中收到。它需要最大。2 连接到所有浏览器都支持的服务器。

请记住,如果有 500 个客户端,则意味着 500 个服务器端 webserver 线程,它们将一起移动,出现负载峰值,因为当有事情发生时,服务器必须同时为每个客户端报告,客户端将处理它几乎同时长,他们将在同一时间开始下一个长请求,从那时起,超时也将同时到期,未来的也将到期。您可以使用 rnd 超时进行欺骗,例如 4 rnd(0..4),但这毫无价值,如果发生任何事情,它们将再次“同步”,所有请求必须同时处理,当发生可报告的事情时。

我已经通过路由器对其进行了测试,并且可以正常工作。我假设,路由器尊重 4..10 延迟,它大约是慢 webapge 的速度(很远,很远),没有路由器认为应该取消它。

我的 PHP 工作是一个协作电子表格,当您按 Enter 键并且内容在多个浏览器中同时更新时,它看起来很棒。玩得开心!

于 2012-10-17T15:32:47.807 回答
2

不,浏览器不会以任何方式影响轮询。我认为该页面上的含义是相同的来源策略-您只能访问与原始页面相同的主机和端口。

对连接本身的唯一已知限制是,您通常只能同时连接两到四个到同一主机。

于 2012-10-15T02:44:32.620 回答
1

ajax 请求的数量没有限制。但是它将在同一主机和端口上。

服务器可以根据其设置限制来自机器的请求。

例如。服务器可以设置,如果在指定时间内来自同一台机器的请求过多,它将拒绝请求。

于 2012-10-18T05:33:06.820 回答
0

在 javascript 代码中出现小错误后,每一步调用 2 个 ajax 请求都会产生无休止的循环。在 firebug 中,我可以看到越来越多的请求,直到 firefox 开始减速、不响应并最终崩溃。

所以,是的,有一个“限制”;)

于 2012-10-18T09:28:25.953 回答