问题 javascript聊天客户端的服务器轮询间隔


我正在为我的网站构建一个基本的小AJAX shoutbox / chat,但我不确定如何实现服务器轮询。

这是我正在考虑的基本程序流程:

  1. 用户进入页面并显示最后10条消息
  2. 要获取其他人发送的消息,客户端javascript将请求带有timestamp参数的URL(设置为客户端收到的最后一条消息的值)
  3. 服务器返回自该时间戳以来的所有消息(最多10个)。

唯一的问题是轮询服务器的频率。显然,每次添加新消息时都应该进行轮询,但是当您只是阅读其他消息时,它需要自动更新。

它应该是一个设定的时间限制吗?例如:每10秒钟。或者,它应根据使用情况而有所不同?例如:5秒后检查。如果没有消息,请不要再检查10秒。如果仍然没有新消息,请检查15秒,然后是20,最多可能每30秒检查一次。每次检测到新消息时,都会将计时器重置为5秒并重新开始。

考虑到我们可以在线同时拥有数百名用户,我只关心在服务器上施加不必要的压力。

......或者我弄错了什么?有没有更好的方法来实现基本的JavaScript聊天?


5477
2018-03-24 03:44


起源



答案:


Comet,由Brian描述是一种很好的技术,但需要服务器上的会话支持,这可能比你想要实现一个简单的聊天框更高级。

实现轮询间隔的最佳方法是假设您有一个聊天窗口,您可以将其最小化以执行其他操作,或者打开以查看是否有新消息。当您处于对话中时,您将经常切换到它(轮询)。如果您暂时没有收到任何消息,您将开始寻找稀有和罕见的消息,直到您偶尔检查它为止。

假设您不需要进行实时打字,您可以在峰值活动时每隔3秒左右轮询一次,如果没有显示5-10个民意调查,则开始调整间隔时间(可能每次都加倍) )直到它达到30-60秒。获取消息应该将轮询间隔重置为几秒,而发送消息应立即轮询,但可能不需要影响轮询的频率。


4
2018-03-24 05:18



这就是提问者概述的内容。你读完了整个问题吗? - Crescent Fresh
我认为关键点在于对成功更新与不必要更新的细微澄清。对于聊天示例,如果存在表示活动的新聊天,则轮询间隔应基线到短间隔(正反馈循环)。如果进行了轮询并且没有新的聊天,那么下一个的间隔应该增加(负反馈循环)。我认为这是一种非常强大而有效的处理轮询的方法。 - Kzqai


答案:


Comet,由Brian描述是一种很好的技术,但需要服务器上的会话支持,这可能比你想要实现一个简单的聊天框更高级。

实现轮询间隔的最佳方法是假设您有一个聊天窗口,您可以将其最小化以执行其他操作,或者打开以查看是否有新消息。当您处于对话中时,您将经常切换到它(轮询)。如果您暂时没有收到任何消息,您将开始寻找稀有和罕见的消息,直到您偶尔检查它为止。

假设您不需要进行实时打字,您可以在峰值活动时每隔3秒左右轮询一次,如果没有显示5-10个民意调查,则开始调整间隔时间(可能每次都加倍) )直到它达到30-60秒。获取消息应该将轮询间隔重置为几秒,而发送消息应立即轮询,但可能不需要影响轮询的频率。


4
2018-03-24 05:18



这就是提问者概述的内容。你读完了整个问题吗? - Crescent Fresh
我认为关键点在于对成功更新与不必要更新的细微澄清。对于聊天示例,如果存在表示活动的新聊天,则轮询间隔应基线到短间隔(正反馈循环)。如果进行了轮询并且没有新的聊天,那么下一个的间隔应该增加(负反馈循环)。我认为这是一种非常强大而有效的处理轮询的方法。 - Kzqai


您可能想要查看所谓的内容 彗星 编程技术将信息流式传输给用户,而不是让客户端轮询服务器。这实际上是一系列技术,其中一些技术可能比其他技术更好,具体取决于具体情况,例如您使用的是哪种服务器以及您需要哪种类型的客户端兼容性。

如果您的服务器一次可以处理大量打开的连接(例如,它不会使用每个连接的整个线程或进程,例如 nginx的 或者 二郎神基于服务器),您可能希望使用长轮询技术,一旦收到一条消息,客户端就会立即请求另一条消息。如果没有可用消息,则服务器只是保持连接打开,可能偶尔发送虚拟数据作为保持连接,直到消息可用。


5
2018-03-24 03:52





老实说,如果你正在实施“基本的小AJAX shoutbox /聊天“, 像 叽里咕噜彗星 等对你来说太过分了。这些东西需要你额外运行 服务器/代理来承担应用服务器和数据库的负载。
当你想到像这样的东西 在线管理 (“乔正在打字......”),然后你的应用程序的事情变得过于复杂(考虑到“聊天”不是你的主要焦点)。
考虑添加来自提供商的小部件 Meebo的 和 Userplane。一旦你扩大了对Jabber等的思考......


3
2018-03-24 05:43



事实上它确实应该是最基本的功能 - nickf


您应该检查其他用户是否每隔5秒左右键入一次,如果另一个用户正在键入,那么您可以每隔1秒检查一次,看看用户是否发送了新消息。实际上,您应该能够每1秒检查一次,看看其他用户是否正在打字,然后每隔0.25秒.5秒检查一下是否有新消息发送。随着宽带被普遍接受,不应该是一个问题。使用较长的轮询超时进行拨号访问。


0
2018-03-24 03:49



虽然可能有数百人。并且这不会要求每个客户端在用户开始输入时以及停止时发送请求吗? - nickf
这是事实,但是在AJAX中,这就是AJAX XMLHTTPRequest对象的设计目标。 - Suroot
对不起这里的双重帖子,但想把这些信息放在那里: en.wikipedia.org/wiki/Comet_(programming)#XMLHttpRequest - Suroot


这是一个非常难的问题,请记住滥用。恶意用户会尽可能频繁地打你,最早的时间戳是假的,这样会对你的数据库服务器造成压力。一定要验证时间戳,或者忽略它,因为不管怎么说每个人都在同一时间?

您可以根据其他用户的响应时间将轮询间隔发送给用户。这是我认为最好的动态。


0
2018-03-24 03:52



是的,我想到了 - 我想我会从给定的时间戳返回最新的10条消息,所以即使有人将其更改为“0”,它们也只会收到最后10条消息。 - nickf
不要使用时间戳,而是向客户端发出令牌,这样您最初会使用令牌为它们标记消息,当它们请求您创建新令牌的消息返回给它们时,使用最新令牌标记新消息。 - Keldon Alleyne


http://jabbify.com/home/comet_service 这是一个由jmvc框架的人提供的基于免费彗星的聊天服务。尚未尝试过,但看起来很有希望。


0
2018-04-18 01:56