【问题标题】:How can I provide real-time notifications without tying up resources?如何在不占用资源的情况下提供实时通知?
【发布时间】:2013-05-17 13:03:10
【问题描述】:

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

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

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

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

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

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

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

TL;博士

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

【问题讨论】:

  • @ZachLeighton 谢谢,在此之前我已经梳理过该页面,但我需要有关如何克服我所面临的限制的具体信息。
  • 你有没有想过使用 Websockets 来代替?
  • 许多请求比长请求处理得更好。由于线程永远不会真正死亡,它们只会被重用。如果最终没有可用线程,它还将允许系统跳过一个循环。现在在某个时候,您会遇到共享主机上的 apache+php 配置问题。之后,也许可以使用一个小型 vps 并切换到 nginx 或我个人最喜欢的 cherokee 并使用 phpfpm,然后您可以构建一个为您的轮询循环保留的实际工作线程
  • 由于线程始终处于打开状态,因此允许轮询脚本完成然后重新启动没有任何开销(如果数据库连接正确完成,则池化 conns 和 prep 之间将几乎没有额外的数据库负载-statements 甚至更好的 memcached 或类似的)意味着您只在运行期间锁定线程,然后立即释放它以供其他进程拾取并使用它这是您可以在 8 个线程上支持超过 8 个用户的方式,因为它们被回收.除非你使用实时套接字和守护进程,否则不要担心调用它总是比 longpoll 更有效

标签: php mysql jquery push-notification


【解决方案1】:

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

来自戴夫,

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

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

目前问题已解决。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 是的,这是正确的。轮询很快,但是长轮询(在完成 AJAX 请求之前等待)占用资源。不同的是,长轮询一到就会得到结果,而轮询只会在新信息进来后下一次发送 AJAX 请求时才取到它。理想情况下,我希望长轮询的优势无需捆绑线程。
    猜你喜欢
    • 1970-01-01
    • 2011-03-24
    • 1970-01-01
    • 2023-03-31
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多