6

我有一个非常简单的长轮询 ajax 调用,如下所示:

(function poll(){
    $.ajax({ url: "myserver", success: function(data){
        //do my stuff here

    }, dataType: "json", complete: poll, timeout: 30000 });
})();

我今天下午刚拿起这个例子,它似乎工作得很好。我正在使用它在我的页面上构建一些 html,据我所知,它几乎是即时的。我有点担心这会让我的服务器上的工作线程保持打开状态,并且如果我在服务器上的负载太大,它将完全停止。有人可以阐明这个理论吗?在后端,我有一个 webapi 服务(.net mvc 4),它调用数据库、构建对象,然后将对象传递回去。在我看来,为了使其正常工作,服务器必须不断调用数据库......这不太好,对吧???

我的下一个问题是客户端确定是否需要更新页面上的 html 的最佳方法是什么?目前,我正在使用 JSON.stringify() 将我的对象转换为字符串,并将返回的字符串与旧字符串进行比较,如果有增量,它会重写页面上的 html。现在还没有一个完整的对象中有很多下降,但它可能会变得非常大,我认为在客户端进行字符串比较可能会占用大量资源......特别是如果它几乎不断地进行。

对我来说,最重要的是:我不确定轮询的工作时间。我只是用谷歌搜索并找到了上面的示例代码并实现了它,从表面上看,它很棒。我只是担心它会陷入困境下来(在服务器上),我将旧结果与新结果进行比较的方式将陷入困境(在客户端)。

非常感谢您提供的任何和所有信息。

TIA。

4

2 回答 2

13

好的,我的两分钱:

  1. 正如其他人所说,SignalR 是经过试验和测试的代码,所以我真的会考虑使用它而不是自己编写。
  2. SignalR 确实更改了一些 IIS 设置以针对此类工作优化 IIS。因此,如果您想实现自己的,请查看SignalR 中完成的 IIS 设置更改
  3. 我想您正在进行长轮询,以便您的服务器可以实现某种形式的服务器推送。请记住,这会将您的无状态 HTTP 机器变成有状态机器,如果您想扩展,这不是很好。负载均衡器后面的长时间轮询并不好:)对我来说,这是服务器推送最糟糕的事情。
  4. ASP.NET 使用 ThreadPool 来处理请求。长轮询将占用 ThreadPool 线程。如果你有太多这样的线程,你最终可能会陷入线程饥饿(和眼泪)。作为一个大概的数字,100 不算太多,但 +1000 是。
  5. 甚至 SignalR 团队也说针对 SingalR 优化的 IIS 框可能没有针对普通 ASP.NET 进行优化,他们建议将这些框分开。所以这意味着成本和开销。

归根结底,如果您正在解决业务问题(而不是因为它很酷),我建议使用长轮询,因为那样会支付其成本、间接费用和令人头疼的问题。

于 2012-12-17T13:46:51.450 回答
10

我同意 SLaks - 即如果您需要使用 WebApi http://www.asp.net/signalr的实时网络,请使用 SignalR 。长轮询很难很好地实现,让其他人处理这种复杂性,即使用 SignalR(WebApi 的自然选择)或 Comet。

SignalR 在诉诸长轮询、Web 套接字、服务器发送事件和永久帧(此处)之前尝试了 3 种其他形式的通信。

在某些情况下,您可能会更好地使用简单的轮询,即每隔一秒左右更新一次……看看这篇文章。但这里引用一段话:

当您的消息量很大时,长轮询不会比传统轮询提供任何实质性的性能改进。事实上,情况可能更糟,因为长时间的投票可能会失控,变成一个不受限制的、连续的即时投票循环。

令人担心的是,如果您的网页上有任何显着负载,您的 30 秒 ajax 查询最终可能会成为您自己的拒绝服务攻击。

如果负载过多,即使是Bayeux ( CometD ) 也会诉诸简单的轮询:

通过使用重新连接和间隔建议字段来限制客户端来解决增加的服务器负载和资源匮乏问题,在最坏的情况下会退化为传统的轮询行为。

至于你问题的第二部分。

如果您使用长轮询,那么理想情况下,您的服务器应该只在实际发生变化时才返回更新,因此您的 UI 应该可能“信任”响应并假设响应意味着新数据。任何服务器推送类型的方法都是如此。

如果您确实返回到简单的轮询pullmethod,那么您可以使用内置的 http 方法来检测使用 If-Modified-Since 标头的更新,这将允许您返回 304 Not Modified,因此服务器将检查时间戳对象,如果自上次请求以来已修改对象,则仅返回 200 和对象。

于 2012-12-17T09:10:46.350 回答