1

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

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

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

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

我设想的更像是这样的:

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

这样,无论有多少用户登录并观看监控页面,服务器每分钟只运行一个查询。O(1) = 好!问题是,即使在我完成所有研究之后,我也无法完全弄清楚如何实现这一点。老实说,我并不完全理解我在寻找什么,因此很难研究解决方案。所以我希望更多开明的开发者能带领我走向正确的方向。

4

2 回答 2

0

你可以用彗星做到这一点。但是您也可以只使用一个 JavaScript 计时器,每分钟左右轮询一次服务器。这取决于您希望获得反馈的速度。不必一直保持 TCP 连接打开。

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

于 2012-06-23T21:07:58.743 回答
0

这个问题的解决方案可以通过一个名为Pusher的应用程序轻松解决,这是一个托管的发布/订阅 API。简而言之,Pusher 提供了两个库,一个用于客户端(订阅者),一个用于服务器(发布者)。

发布者可以是您服务器上的单个脚本(有很多可用的语言)设置为以您希望的任何时间间隔运行。每次运行时,它都会连接到一个通道并发布它生成的任何数据。客户端是通过 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

于 2012-12-07T01:11:28.620 回答