3

为什么 HTTP 轮询如此滞后?

我拥有的是一个按钮,每当用户单击它时,MySQL 数据库字段就会更新,并将值显示给用户。我每 800 毫秒轮询一次,它非常滞后/故障。有时单击按钮时不会注册它。而且我实际上需要比每 800 毫秒更频繁地进行轮询。

这也是网站上一次只有 1 个用户......最终会同时有很多用户。

4

5 回答 5

2

HTTP-streaming/Long-polling/Websockets 而不是轮询

当您需要实时信息时,您应该避免(经常)轮询。下面我将尝试解释为什么这是错误的。您可以将其比作汽车后座的一个孩子,每秒钟都在尖叫“我们还在那里吗”,而您却一直在回答“我们还没有”。

相反,您希望拥有类似长轮询/HTTP 流或 websockets 的东西。您可以将其与汽车后座的孩子进行比较,告诉您“我们在那儿”时让他知道,而不是每秒钟都问我们。你可以想象这比前面的例子更有效率。

老实说,我不认为 PHP 是此类应用程序的正确工具(目前)。您可以使用的一些选项是:

托管解决方案:

  • http://pusherapp.com

    Pusher 是一个托管 API,用于通过 WebSockets 向 Web 和移动应用程序快速、轻松、安全地添加可扩展的实时功能。


    我们的免费沙盒计划包括每天最多 20 个连接和 100,000 条消息。准备好后,只需升级到付费计划。

  • http://beaconpush.com/

    Beaconpush 是一种推送服务,用于使用 HTML5 WebSockets 和 Comet 创建实时 Web 应用程序。

主持自己:

  • http://socket.io

    Socket.IO 旨在使每个浏览器和移动设备中的实时应用程序成为可能,模糊不同传输机制之间的差异

当变得非常大时,“自己托管”解决方案的成本会降低,但另一方面,使用 pusherapp 之类的东西会让你更容易开始(友好的 API),而且也不那么昂贵。例如 pusherapp 的“Bootstrap”每天可以有 100 个并发连接和 200,000 条消息,每月只需 19 美元(但是当小的 beaconpush 更便宜时 => 算一下 :))。作为旁注,此计划不包括 SSL,因此不能用于敏感数据。我想拥有一台专用机器(VPS)将花费您大约相同数量的钱(对于一个简单的网站),您还必须自己管理流媒体解决方案,但是当变得更大时,这可能更具吸引力。


内存而不是光盘

每当用户单击它时,MySQL 数据库字段就会更新并将值显示给用户

将磁盘 I/O(标准模式下的 MySQL)与内存进行比较时,速度非常慢。您应该使用内存数据库,例如redis(也有持久快照)或 memcached(完全在内存中)来加快进程。我本人真的很喜欢 redis,因为它具有惊人的速度、简单性和持久的快照。http://redistogo.com/提供了一个 5MB 内存的免费计划,它可能会满足您的需求。如果不是每月 5 美元的迷你计划可能会覆盖您,但是当变得更大时,VPS 会更便宜,并且在我看来是首选的解决方案。


最佳解决方案

最好的解决方案(特别是如果你变大了)是使用 VPS(花钱)自己托管 socket.io/redis。如果真的很小,我会使用 redistogo,否则我会自己托管。我也会开始使用像 beaconpush/pusherapp 这样的东西,因为它很简单(立即开始)。托管 socket.io(建议在你自己的机器上玩它以备变大)非常简单,但在我看来比 beaconpush/pusherapp 更难。

于 2011-06-16T02:10:21.047 回答
1

滞后/故障?听起来像一个客户端问题。按钮也是如此。我会先把你的 JavaScript 整理好。

至于轮询,0.8 听起来有点时间紧迫。我不了解大多数国家,但在第三世界,简单的网络数据包可能会延迟几秒钟。(更不用说连接丢失、数据包丢失和光速了。)您的应用程序准备好应对所有这些了吗?

至于另一种方法,我同意@Vern,因为中断驱动的方法会好得多。在 HTTP 术语中,它转换为一个长期存在的 HTTP 请求,在服务器有一些实际数据要发送之前不会收到响应,从而最大限度地减少延迟和带宽。(AFAIK)它是一种比 AJAX 更古老的技术,但最近才被命名。搜索“COMET”,您将同时获得客户端和服务器端库。

于 2011-06-16T01:34:47.553 回答
0

有很多事情可能会导致您遇到的滞后。您的服务器可能能够足够快地处理请求,但是如果您的客户端和服务器之间的连接很慢,那么您会看到明显的延迟。

您应该尝试的第一件事是 ping 服务器并查看您获得的响应时间。

其次,您可能需要考虑中断驱动的方法,而不是轮询。这意味着只有当您的服务器回复时,您才会发出下一个请求。这是有道理的,因此许多客户端不会向服务器发出大量请求,直到服务器无法应对。尤其如此,那么您的请求的 RTT(往返时间)很长。

希望能帮助到你。干杯!

于 2011-06-16T01:20:41.010 回答
0

一个好的起点是在 Mozilla Firefox 中使用像Firebug这样的工具,它可以让您观察发送到服务器的请求并查找瓶颈。

Firebug 将分解请求的每个部分,因此您可以查看您是否在与服务器通信时遇到问题,或者是否需要很长时间才能得到响应。

于 2011-06-16T01:25:53.390 回答
0

除了@Vern 的回答,我还要说,如果可能的话,我会让服务器提前缓存数据,然后所有客户端将从同一个缓存中提取,并且不需要单独的 MySQL 调用来为每个客户端获取相同的数据更新。然后,只要实际数据库数据发生变化,您只需让 PHP 更新缓存即可。

通过缓存,我的意思是让 php 写入服务器端的文件,然后客户端将简单地查看该文件的内容以查看最新信息。可能有更好的缓存方法,但由于我以前从未亲自做过,这是我想到的第一个解决方案。

于 2011-06-16T01:26:50.947 回答