【问题标题】:Do browsers limit AJAX polling rate? What is the limit?浏览器是否限制 AJAX 轮询率?极限是多少?
【发布时间】:2012-10-05 12:53:20
【问题描述】:

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

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

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

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

问题

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

感谢您的帮助...

斯蒂芬

【问题讨论】:

    标签: ajax xmlhttprequest limit polling rate


    【解决方案1】:

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

    看看这个Google implementation

    这是捕获超时错误的awesome implementation

    您可以找到 Firefox 的详细信息HERE

    Internet Explorer 的细节在 Windows 注册表中进行控制。

    也可以看看this question

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

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

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

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

    滑块的当前值与当前“页面”匹配。由于我每页只显示 5 篇文章,而且我不能完全加载数千篇文章而不会对性能产生严重影响,因此我加载了当前页面的文章。我通过向 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 中的原生多线程:)(他们怎么没想到这个?! ?!)

    【讨论】:

    • 你有任何关于 Firefox 限制的信息吗?是否引用了说明 Google Chrome 限制的可靠资源(也可以链接到浏览器的相应源代码文件)?
    • Google 闭包库源现在托管在github.com/google/closure-library
    【解决方案2】:

    Stefan,下面的快速回答:

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

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

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

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

    【讨论】:

    • 这对 RoManiac 很有帮助...这些都是很好、可靠的参考资料。
    • 我想给你一个答案,而不是另一个问题 :) alex23 对限制 XHR 请求很冗长,这个解决方案可能不适合你的 intermittent JS 不当行为。您决定哪个答案最有利于其他 SO 用户:)
    • 投票支持 browserscope.org 链接。正是我想要的。
    【解决方案3】:

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

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

    【讨论】:

    • 当然可能是这样。由于没有人回应,我也想到了对上述说法的这种解释。
    【解决方案4】:

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

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

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

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

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

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

    【讨论】:

      【解决方案5】:

      没有限制 ajax 请求。但是它将位于同一主机和端口上。

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

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

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

        • 由于无限的 JavaScript 循环而不是 Ajax 请求,它的浏览器速度变慢了 :)
        • 是的,当然有本地系统资源的限制……但这不重要。
        • @user1531437 确定!这就是为什么引用我的帖子中的限制 :) Imo 最好的例子是只有系统资源限制 ajax 请求
        猜你喜欢
        • 1970-01-01
        • 2011-07-19
        • 1970-01-01
        • 2012-05-20
        • 1970-01-01
        • 1970-01-01
        • 2011-03-05
        • 2012-05-17
        • 1970-01-01
        相关资源
        最近更新 更多