【问题标题】:Server polling intervals for a javascript chat clientjavascript 聊天客户端的服务器轮询间隔
【发布时间】:2009-03-24 03:44:11
【问题描述】:

我正在为我的网站构建一个基本的小型 AJAX 喊话框/聊天,但我不确定如何实现服务器轮询。

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

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

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

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

考虑到我们可能有数百名用户同时在线,我只是担心会给服务器带来不必要的压力。

...还是我把整个事情搞错了?有没有更好的方法来实现基本的 JavaScript 聊天?

【问题讨论】:

    标签: javascript ajax


    【解决方案1】:

    您可能希望研究所谓的Comet 编程技术,将信息流式传输给您的用户,而不是让客户端轮询服务器。这实际上是一系列技术,根据具体情况,其中一些可能比其他技术更好,例如您使用的是哪种服务器以及您需要哪种客户端兼容性。

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

    【讨论】:

      【解决方案2】:

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

      实现轮询间隔的最佳方式是想象您有一个聊天窗口,您可以将其最小化以执行其他操作,或者打开以查看是否有新消息。当你在谈话中时,你会经常切换到它(轮询)。如果你有一段时间没有收到任何消息,你会开始变得越来越稀有,直到你只是偶尔查看一下。

      假设您不需要进行实时输入,您可以在活动高峰时每 3 秒左右轮询一次,如果 5-10 次轮询没有显示任何内容,则开始增加间隔(可能加倍每次),直到达到 30-60 秒。取回消息应将轮询间隔重置为几秒钟,而发送消息应立即轮询,但可能不需要影响轮询频率。

      【讨论】:

      • 这正是提问者所概述的。您是否阅读了整个问题?
      • 我认为关键点是成功更新与不必要更新的微妙澄清。对于聊天示例,如果有新聊天,则表明活动,并且轮询间隔应以短间隔为基准(正反馈循环)。如果轮询完成并且没有新的聊天,那么下一个的间隔应该增加(负反馈循环)。我认为这是处理轮询的一种非常强大和有效的方法。
      【解决方案3】:

      老实说,如果你正在实现“基本的小 AJAX 留言框/聊天”,那么像 JabberComet 等对你来说是多余的。这些事情将需要您运行额外的 服务器/代理承担应用服务器和数据库的负载。
      当您想到presence management(“Joe 正在打字...”)之类的内容时,您的应用程序就会变得过于复杂(考虑到“聊天”并不是您的主要关注点)。
      考虑添加来自 MeeboUserplane 等提供商的小部件。一旦你扩大规模,想想 Jabber 之类的……

      【讨论】:

      • 确实应该是最基本的功能
      【解决方案4】:

      你应该每隔 5 秒左右检查一下其他用户是否正在输入,如果其他用户正在输入,那么你可以每隔 1 秒检查一下用户是否发送了新消息。但实际上,您应该能够每 1 秒检查一次以查看其他用户是否正在输入,如果他们正在输入,则每 0.25-0.5 秒检查一次是否已发送新消息。随着宽带在互联网上被广泛接受,应该不是问题。为拨号访问设置更长的轮询超时时间。

      【讨论】:

      • 可能有数百人。这不是要求每个客户端在用户开始输入和停止输入时都发送请求吗?
      • 这是真的,但是在 AJAX 中,这就是 AJAX XMLHTTPRequest 对象的设计目的。
      • 对不起这里的双重帖子,但想把这个信息放在那里:en.wikipedia.org/wiki/Comet_(programming)#XMLHttpRequest
      【解决方案5】:

      这是一个非常难的问题,请记住滥用行为。恶意用户会尽可能频繁地攻击您,并伪造最早的时间戳,从而对您的数据库服务器造成压力。一定要验证那个时间戳,或者忽略它,因为不应该每个人都在同一时间吗?

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

      【讨论】:

      • 是的,我想到了——我想我会返回自给定时间戳以来的最新 10 条消息,因此即使有人将其更改为“0”,他们也只会收到最后 10 条消息。
      • 不要使用时间戳,而是向客户端发出令牌,您最初使用令牌为他们标记消息,当他们请求这些消息时,您创建一个新令牌返回给他们,标记新的带有最新令牌的消息。
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        这样做的专业方法是使用 WebSocket javascript 连接。例如,您可以使用https://socketsbay.com/ 之类的免费服务,并使用

        进行连接

            // Create WebSocket connection.
            const socket = new WebSocket('wss://socketsbay.com/wss/v2/[ChannelId]/[ApiKey]/');
        
            // Connection opened
            socket.addEventListener('open', function (event) {
                socket.send('Hello Server!');
            });
        
            // Listen for messages
            socket.addEventListener('message', function (event) {
                console.log('Message from server ', event.data);
            });

        您可以忘记服务器池时间,因为它是实时的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-04
          • 2015-06-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-09
          • 2014-05-17
          • 2017-07-06
          相关资源
          最近更新 更多