J.C. Yamokoski
J.C. Yamokoski

Reputation: 1014

Is Comet (server push) the answer I'm looking for?

I have a web application that I am trying to make more efficient by reducing the number of database queries that it runs. I am inclined to implement some type of Comet style solution but my lack of experience in this department makes me wonder if a more simple solution exists.

For the sake of brevity, let's just say that I have a database that contains a list of systems on a network and their current status (whether they are up or down). A user can sign into the web app and select which systems she is interested in monitoring. After which she can visit the monitoring page which displays the number of systems that are currently down.

As of now the count is refreshed using Ajax... every minute the client sends a request to the server which in turn runs a query against the database to get the current count and returns the result to the client. I know this in inefficient; for every client that logs in, another query is run against the database every minute. O(n) = bad!

I know that I can use some type of caching, such as memcached, but it still means there is a request for every user every minute. Better, but I still feel as if it's not the best solution.

I envision something more like this:

That way it doesn't matter how many users are logged in and watching the monitoring page, the server only ever runs one query per minute. O(1) = good! The problem is that even after all of the research I've done I can't quite figure out how to implement this. To be honest I don't completely understand what it is that I am looking for, so that makes it very difficult to research a solution. So I am hoping that more enlightened developers can lead me in the right direction.

Upvotes: 1

Views: 186

Answers (2)

J.C. Yamokoski
J.C. Yamokoski

Reputation: 1014

The solution to this issue can easily be solved with an app called Pusher, which is a hosted publish/subscribe API. In a nut shell, Pusher provides two libraries, one for the client (the subscriber) and one for the server (the publisher).

The publisher can be a single script on your server (there are quite a few languages available) set to run at whatever interval you desire. Each time it runs it will connect to a channel and publish to it whatever data it generates. The client is created via a bit of JavaScript in your web app, and whenever a user navigates to your page, the client subscribes to the same channel your server script is publishing to and receives the data as soon as it becomes available and then can manipulate it however you see fit.

The server:

#!/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))
);

The client:

<!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>

So, in this case regardless of how many clients access the page there is only one database query running, and at each interval all the subscribed clients will be updated with the new data.

There is also an open source server implementation of the Pusher protocol written in Ruby called Slanger.

Upvotes: 1

Wolfgang
Wolfgang

Reputation: 2407

You can do it with Comet. But you can also just have a JavaScript timer that polls the server every minute or so. That depends on how quickly you want the feedback. Its not necessary to keep the TCP connection open the whole time.

Also, the way you find out about the status of the servers is independent from the way the clients get this information. You would not want to update the servers' status every time a client requests it. Instead you would have a timer on the app server which polls the server status and then stores it. Client requests would be fed from this stored status instead of the actual live status.

Upvotes: 0

Related Questions