1

我正在使用 AJAX 在页面上实现长轮询,每当将新行插入数据库时​​,我想更新该页面。完成此操作的方法是使用 jQuery.ajax()调用,例如,poll.php?ky=41它会多次查询数据库中 ID 为> 41(中间有一小段等待)的行,直到指定的超时。如果有结果,或者在给定的超时之后,它将立即完成请求。

实际上,这使隐藏的连接始终对服务器打开,等待它响应,以便获得通知。

这行得通,但我使用的是 DreamHost,并且在php53.cgi生成了 8 个工作进程之后,直到一次超时,对我的站点的请求都没有得到满足(即永远加载)。这会影响我网站上的所有其他页面。HTTP 服务器是 Apache 2.2.22-14。

为了缓解这个问题,我减少了延迟和超时,使其更接近常规轮询,并在一段时间没有更新时增加了更长的延迟。这意味着通知可能会晚几秒钟,但到目前为止我的服务器运行良好。

我担心的是这将扩展得有多好(或者更确切地说,有多差)。

我的问题是:鉴于我在共享主机(DreamHost)上,并且此页面必须与尽可能多的浏览器兼容(移动设备除外),是否有更有效的方式从服务器获取即时“推送”通知?

或者,我还有什么其他选择?我应该切换回常规投票吗?

TL; 博士

轮询很快,但是长轮询(在完成 AJAX 请求之前等待)占用资源。不同的是,长轮询一到就会得到结果,而轮询只会在新信息进来后下一次发送 AJAX 请求时才取到它。理想情况下,我希望长轮询的优势不会占用线程并导致其他用户在提供页面之前等待。

4

2 回答 2

1

在这种情况下,解决方案是简单地使用常规轮询(例如,每 500 毫秒一次 AJAX 调用)来获得快速通知,而不是使用长轮询和捆绑线程。

从戴夫,

许多请求比长请求处理得更好。由于线程永远不会真正死亡,它们只会被重用。如果最终没有可用线程,它还将允许系统跳过一个循环。现在在某个时候,您会遇到共享主机上的 apache+php 配置问题。之后,也许可以使用一个小型 vps 并交换到 nginx 或我个人最喜欢的 cherokee 并使用 phpfpm 然后您可以构建一个为您的轮询循环保留的实际工作线程

由于线程始终处于打开状态,因此允许轮询脚本完成然后重新启动没有任何开销(如果数据库连接正确完成,则池化 conns 和 prep-statements 甚至更好的 memcached 或类似语句之间几乎没有额外的数据库负载)意味着您仅在运行期间锁定线程,然后立即将其释放以供其他进程拾取并使用它,这就是您如何在 8 个线程上支持超过 8 个用户,因为它们被回收。除非您使用实时套接字和守护进程,否则不必担心调用它总是比 longpoll 更有效

至此,问题已解决。

于 2013-05-19T21:57:02.440 回答
0

我认为在 php 中,每个打开的连接都意味着一个正在运行的线程。您必须缩短连接时间并使用轮询。

唯一的帮助是尽可能快地组织轮询,因此我会尝试为每个会话存储一个非常简单的信息队列,例如apc_fetch/apc_store(如果您的应用程序只有一个 apache 运行)。一个非常简单的页面has_update.php?session_id只读取该状态行并返回 0 或 1,并且大多数时候以尽可能最小的格式返回 0。因此,每秒 5 倍的速度不应该很快成为性能问题。

当且仅当has_update.php返回 1 时,应该触发正常的 ajax 调用。

于 2013-05-17T13:14:33.103 回答