Comet(服务器推送)是我正在寻找的答案吗?

时间:2012-06-23 16:16:03

标签: javascript ajax performance optimization comet

我有一个Web应用程序,我试图通过减少它运行的数据库查询的数量来提高效率。我倾向于实现某种类型的Comet风格解决方案,但我在这个部门缺乏经验让我想知道是否存在更简单的解决方案。

为了简洁起见,我们假设我有一个数据库,其中包含网络上的系统列表及其当前状态(无论它们是向上还是向下)。用户可以登录Web应用程序并选择她有兴趣监控的系统。之后,她可以访问监控页面,该页面显示当前关闭的系统数量。

截至目前,使用Ajax刷新计数...客户端每隔一分钟向服务器发送一个请求,然后服务器对数据库运行查询以获取当前计数并将结果返回给客户端。我知道效率低下;对于每个登录的客户端,每分钟都会对数据库运行另一个查询。 O(n)=坏!

我知道我可以使用某种类型的缓存,例如memcached,但它仍然意味着每分钟都有一个对每个用户的请求。更好,但我仍觉得好像不是最好的解决方案。

我设想更像这样的东西:

  • 服务器每隔一分钟运行一次查询,以便为当前关闭的所有系统提取计数。
  • 服务器然后将此数据推送给感兴趣的客户端。

这样,无论有多少用户登录并观看监控页面,服务器每分钟只运行一次查询。 O(1)=好!问题是即使经过我所做的所有研究,我也无法弄清楚如何实现这一点。说实话,我并不完全明白我在寻找什么,所以这使研究解决方案变得非常困难。因此,我希望更多开明的开发人员能够引导我朝着正确的方向前进。

2 个答案:

答案 0 :(得分:0)

你可以用Comet来做。但是你也可以拥有一个JavaScript计时器,每分钟左右轮询一次服务器。这取决于您希望反馈的速度。没有必要一直保持TCP连接打开。

此外,您了解服务器状态的方式与客户端获取此信息的方式无关。每次客户端请求时,您都不希望更新服务器的状态。相反,您将在应用服务器上有一个计时器,它会轮询服务器状态然后存储它。客户端请求将从此存储状态而非实际实时状态中提供。

答案 1 :(得分:0)

使用名为Pusher的应用程序可以轻松解决此问题的解决方案,该应用程序是托管的发布/订阅API。在坚果壳中,Pusher提供了两个库,一个用于客户端(订户),另一个用于服务器(发布者)。

发布者可以是服务器上的单个脚本(there are quite a few languages available),设置为以您希望的任何间隔运行。每次运行时,它都会连接到一个通道并向其发布它生成的任何数据。客户端是通过Web应用程序中的一些JavaScript创建的,每当用户导航到您的页面时,客户端都会订阅您的服务器脚本发布到的相同通道,并在数据可用时立即接收,然后可以操作但是你认为合适。

服务器:

#!/usr/bin/php
<?php
require('Pusher.php');

$dbh = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
foreach($dbh->query('SELECT hostname FROM systems WHERE status = 0') as $row) {
    $systems[] = $row['hostname'];
}
$pusher = new Pusher($pusher_key, $pusher_secret, $pusher_app_id);
$pusher->trigger(
    'my-channel',
    'my-event',
    array('message' => implode('<br />', $systems))
);

客户:

<!DOCTYPE html>
<html>
  <head>
    <title>Pusher Test</title>
    <script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
    <script src="http://js.pusher.com/1.12/pusher.min.js" type="text/javascript"></script>
    <script type="text/javascript">
      var pusher = new Pusher(key);
      var channel = pusher.subscribe('my-channel');
      channel.bind('my-event', function(data) {
        $('#systems').html(data.message);
      });
    </script>
  </head>
  <body>
    <div id="systems"></div>
  </body
</html>

因此,在这种情况下,无论有多少客户端访问该页面,都只运行一个数据库查询,并且在每个时间间隔内,所有订阅的客户端都将使用新数据进行更新。

还有一个用Ruby编写的Pusher协议的开源服务器实现,名为Slanger