我不知道哪种方法最有效。有人能帮我找出更好的算法吗。
好吧,让我们举一些像facebook这样的例子,当用户发布帖子时,它会在没有任何页面刷新的情况下更新给他的朋友,我们通过ajax请求知道它。但是,我们怎么能知道有人发布了一个新东西呢?这可能就像每隔2秒设置一个计时器,然后发送一个针对某个表的ajax请求,并检查某个用户是否发布了内容。对吧?但是有没有办法不设置计时器,因为每2秒执行一次操作可能会导致严重的服务器问题?我想是的?只是想知道是否有更好的方法来代替设置计时器?
非常感谢您的帮助。
目前Facebook和谷歌采用的是一种称为长轮询的技术。
这是一个简单的系统,客户端可以通过这个系统向服务器发出AJAX请求。服务器接收请求并检查它是否具有请求所需的数据。否则,请求将保持打开状态,但由服务器推迟。服务器获得数据后,请求就会被处理并返回给客户端。
如果你打开脸书,你会看到请求被发布到脸书上,大约需要55秒才能完成。Gmail和其他一些似乎有某种推送系统的网络应用程序也是如此。
以下是如何处理这些请求的一个简单示例:
-
客户:
- 具有
timestamp 0
的初始AJAX请求
- 具有
-
服务器:
- 通过检查服务器上数据的时间戳,将请求与
timestamp 0
进行比较。假设服务器上的数据具有timestamp 234
- 客户端戳与服务器数据上的当前戳不同,因此我们返回新数据
- 通过检查服务器上数据的时间戳,将请求与
-
客户:
- 客户端获取数据并立即发布一个带有
timestamp 234
的新AJAX请求 - 然后我们处理新数据并适当地更新网页
- 客户端获取数据并立即发布一个带有
-
服务器:
- 将带有
timestamp 234
的请求与服务器上数据的当前戳进行比较 - 邮票的价值是相同的,所以我们去睡觉
- 服务器数据正在更新,并且戳值现在为
timestamp 235
- 睡眠请求会被唤醒并返回更新值
- 将带有
您可以阅读更深入的实时更新机制解释。
只有我的两分钱,但我之前通过拥有两个Web服务解决了类似的问题。基本上,一个方法与HaveNewData()
和另一个GetData()
类似(在我的案例中,我有许多Web服务想要调用)。
因此,基本上定期调用HaveNewData()
(我认为在任何情况下,每2秒调用一次都是不好的设计,也是不必要的),并为该方法返回一个简单的0或1(最小数据)。如果HaveNewData()
返回1,则拨打昂贵的网络服务电话。或者,当没有新的数据可用时,你也可以在主Web服务中返回一个null值,根据我的经验,这至少是"相当"合理的。
长轮询是一种很好的技术,但与任何解决方案一样,效果取决于许多变量,包括硬件设置,因此没有绝对的解决方案。
请注意,长轮询使连接保持活动状态,可能会导致许多客户端出现性能问题。
您的解决方案应考虑:-
- 它需要几乎实时吗(例如股票行情机)
- ajax数据/输出更改的频率(聊天与新评论)
- 导致ajax数据/输出更改的事件触发的频率。这将规定如何生成缓存
当谈到ajax时,你应该是一个节俭的人。请求&应根据需要作出回应。如果没有一个深思熟虑的缓存解决方案,ajax实现的成功将是不完整的,该解决方案更基于事件而不是基于请求。
以下是我们在项目中发现有用的一种技术的简化版本:-
- 发出的每个Ajax轮询请求都将包含output_hash,这是服务器先前返回的数据摘要
- 服务器根据它将从最好存储在缓存中的数据源生成的输出的最近散列来检查这个output_hash
- 如果不同,则它将提供新内容以及新的output_hash。否则是一个小响应/未修改以表示没有新内容
在我们的解决方案中,我们还对下一次轮询的间隔进行了动态计算。保持间隔动态可以让服务器控制请求。例如,让我们假设大多数评论/回答发生在前1小时,除此之外,将间隔时间设置为1秒是没有意义的,因此服务器可以随着时间的增加而动态地将其增加到2、3甚至5秒,而不是将间隔硬编码为2秒。同样,如果旧帖子中有大量活动,则可以缩短间隔时间。
我们还检查了空闲客户和其他事情。