Increasingly people expect websites to be interactive and respond to events in real time. This has been common for chat and instant messaging systems, but now we need to develop real time interaction into more and more web systems. We may need to push new items into a list, or update information as it changes in real time.
This is not the way web servers work, they serve content in response to a request and then they are done. It is static. But we need to make it persistent, or at least appear persistent.
Ideally I would use JavaScript frontend and backend with Socket.IO to create the bidirectional event-based communication between the browser and server.
This however is not always possible and we often have to achieve the same result in a LAMP (Linux, Apache, MySQL, PHP) environment.
There are two main options:
- A “long polling” approach where requests sleep on the server until a new data or changes are found, or until the timeout occurs (or approaches)
- A “heartbeat” approach where regular requests are made to check for new data or changes, eg every 5 seconds
There are pros and cons to each approach. A heartbeat involves much more network traffic, while long polling can use a lot of server resources as each connection to the server commits resources.
PHP long polling
The general approach is to check for new data and if none then sleep for a period of time before checking again and return data if found.
//check for new data, if returns false then sleep for 5 seconds and try again
while(!$data = has_event_happened()) {
sleep(5);
}
echo json_encode($data);
Normally has_event_happened() would be a database query to check for new data.
The front end implementation could be equally simple using jQuery:
function doPoll() {
$.get("poll.php", {}, function(result) {
//do something with your event
//run the poll again as soon as the response comes back
doPoll();
}, 'json');
}
$(document).ready(function() {
$.ajaxSetup({
//set global AJAX timeout to close to your desired php timeout setting, eg 5 mins
timeout: 1000*60*5
});
//do the first poll
doPoll();
});
In this example a new request is made every 5 mins (if no new data sooner) and new data is checked on the server every 5 seconds. In theory the latency is approximately 5 seconds since new data sent to the front end within 5 seconds of a change.
That’s about as simple as it gets so clearly you’d need to build in appropriate event management and error logging and reporting.
If you’re not careful Apache will quickly tie up all the “worker threads” and leave it unable to respond to other requests. In many cases this will rule out long polling as an option but with a bit of server setup tweaking it can be a viable option.
Heartbeat
This approach is very similar to the long poll except that the sleep occurs on the client side rather than server side. With long polling new data will be sent to the front end once detected server side. With the heartbeat approach the front end waits between requests and the back end returns the result immediately as requested.
//check for new data
$data = check_for_event();
//return what was found
echo json_encode($data);
The front end using jQuery uses a timeout to wait 5 seconds between requests.
function doPoll() { //set timeout to 5 seconds setTimeout( function() { $.get("poll.php", {}, function(result) { //do something with your event //call the poll function again as soon as the response comes back doPoll(); }, 'json'); }, 50000); } $(document).ready(function() { //do the first poll doPoll(); });
Again this is just about as simple an implementation as you can get. The latency of this example is effectively the same as the long polling example.
Regardless of which approach you use you should make sure do load testing and calculations to ensure your server resources are sufficient.
I generally use a PHP framework that allows AJAX requests to be as lightweight as possible to further reduce server load. AJAX requests don’t need any templating so I don’t instantiate a templating engine (such as Smarty, Mustache, Twig, etc).