扩展聊天应用-短轮询vs长轮询(AJAX,PHP)

34

我运营一个网站,允许用户通过浏览器聊天(类似Facebook聊天),请问最好的处理实时互动的方法是什么?(目前我每30秒进行一次轮询以更新在线用户和新消息,同时在聊天页面上每秒进行一次轮询以获取新消息。)

我考虑过以下几点:

  • HTML5 Web Sockets:这个方案没有使用,因为它不适用于所有浏览器(只支持Chrome)。
  • Flash Sockets:这个方案没有使用,因为我想要最终支持移动Web。

目前,我正在使用短轮询,因为我不知道可扩展性如何的AJAX长轮询。我现在从servint运行VPS服务器(运行apache)。我应该使用长轮询还是短轮询?我不需要绝对即时的响应时间(只需要足够好的聊天应用程序)。这样频繁地进行短轮询是否会使我的服务器崩溃?如何扩展?请帮帮我!


1
我知道Apache通常不能很好地处理许多同时连接。而且也意识到可能有其他针对这种情况的解决方案(如nodejs等)。但现在,我想避免重写整个应用程序。 - Andy Hin
实现不同平台的多个解决方案怎么样?例如,如果支持HTML5,则浏览器使用HTML5;如果支持Flash,则浏览器使用Flash;如果以上两者都不支持,则浏览器使用Ajax。 - binaryLV
您可能会对这篇文章感兴趣:http://urbanairship.com/blog/2010/09/29/linux-kernel-tuning-for-c500k/ - Michael Mior
3个回答

45

几点注意事项:

  • 每秒轮询过于频繁,每隔几秒钟检查一次也可以使应用程序感到非常快速响应。
  • 为了节省数据库的流量和加速响应,请考虑使用内存缓存来存储未传递的消息。您仍然可以将消息持久化到数据库中,只需使用内存缓存查询新消息即可避免每个用户每x秒钟向数据库发出查询。
  • 在x秒钟的不活动后超时用户的聊天以停止向服务器轮询。这确保留下窗口不会继续产生流量。对于超时的会话提供一个简单的“还在那里吗?继续聊天。”链接,并在超时之前警告用户以便他们可以延长超时。
  • 我建议首先使用轮询而不是comet/long polling/sockets。轮询易于构建和支持,并且在短期内很可能能够很好地扩展。如果您获得大量流量,可以将硬件和负载均衡器投入问题进行扩展。整个web就是基于轮询的-轮询肯定可以扩展。在复杂的替代方案如comet/long polling/等等有意义之前,需要大量的流量才能证明额外的开发时间/复杂性得到证明。

你的最后一点非常有帮助 - 我一直在尝试决定我的应用程序中第一个轮询实现需要多具备未来性,我想我会采纳你的建议,快速实现简单的轮询,然后计划一个智能的长期解决方案。 - simmer

23

在 Cometd 和 Node.js 出现之前,每个人都曾经做过这件事情。

我认为问题在于 Apache 上的 PHP 请求非常昂贵。如果你的聊天应用程序每秒检查一次消息,你会发现自己处于一种 Apache 没有足够资源响应请求的情况下。我认为需要改进的另一个领域是改进聊天应用程序的上下文。

如果没有新消息,为什么要每秒更新?

你可以使用以下一些技术:

  • 为客户端提供轻量级端点,该端点包含关于聊天会话的一些上下文信息,如是否有新消息、有多少条消息等。客户端可以通过立即更新或者当没有新消息时不更新来响应此端点。此端点可以通过 HTTP 请求提供一个简单的 JSON 对象。你可以保证该状态消息将是固定大小的,并且如果状态的响应不改变,则可以降低其更新频率。

  • 在你的 JavaScript 轮询中进行简单的衰减,在客户端连续几次收到相同的服务器响应后,你可以按设置的时间增加轮询间隔。目前你说的是每秒钟一次。如果你这样做,你可以把它递增到每 2、4、6、8、10 秒钟一次。只要服务器的响应发生变化,你就可以重置衰减。

一些优化:

  • 使用 PHP 编译缓存,如 APC。

  • 对所有请求设置较短的超时时间,你不希望任何请求挂起你的服务器。

  • 优化你的 PHP 代码,使它变得更加简洁和快速。

  • 运行一些负载测试,以了解你的极限。

  • 经常进行性能基准测试,以确保你的应用程序变得更快。

  • 检查 Apache 日志,寻找整个应用程序的健康状况和响应时间的迹象。

当需要扩展时,添加新的服务器并使用负载均衡器分配请求。我曾经非常成功地使用 Varnish 和 HAProxy,它们的设置也不复杂。


动态增量是我从未想过的,真正的好点子。 - JayIsTooCommon

1

如果我是你,我会选择一个使用HTML5 Web Sockets但在HTML5不可用时回退到Flash Sockets的库,掉队的浏览器应该很少。

此外,你应该放弃PHP或者用Python或Ruby编写的带线程的Socket服务器来补充它,使用em-websocket。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接