Server-Sent Events Vs Polling

Server-Sent Events vs Polling

Ajax polling adds a lot of HTTP overhead since it is constantly establishing and tearing down HTTP connections. As HTML5 Rocks puts it "Server-Sent Events on the other hand, have been designed from the ground up to be efficient."

Server-sent events open a single long-lived HTTP connection. The server then unidirectionally sends data when it has it, there is no need for the client to request it or do anything but wait for messages.

One downside to Server-sent events is that since they create a persistent connection to the server you could potentially have many open connections to your server. Some servers handle massive numbers of concurrent connections better than others. That said, you would have similar problems with polling plus the overhead of constantly reestablishing those connections.

Server-sent events are quite well supported in most browsers, the notable exception of course being IE. But there are a couple of polyfills (and a jQuery plugin) that will fix that.

If you are doing something that only needs one-way communication, I would definitely go with Server-sent events. As you mentioned Server-sent events tend to be simpler and cleaner to implement on the client-side. You just need to set up listeners for messages and events and the browser takes care of low-level stuff like reconnecting if disconnected, etc. On the server-side it is also fairly easy to implement since it just uses simple text. If you send JSON encoded objects you can easily turn them into JavaScript objects on the client via JSON.parse().

If you are using PHP on the server you can use json_encode() to turn strings, numbers, arrays and objects into properly encoded JSON. Other back-end languages may also provide similar functions.

Ajax polling vs SSE (performance on server side)

No way is 1 request per minute always better for Ajax, so that assumption is flawed from the start. Any kind of frequent polling is nearly always a costly choice. It seems from our previous conversation in comments of another question that you start with a belief that an open TCP socket (whether SSE connection or webSocket connection) is somehow costly to server performance. An idle TCP connection takes zero CPU (maybe every once in a long while, a keep alive might be sent, but other than that, an idle socket does not use CPU). It does use a bit of server memory to handle the socket descriptor, but a highly tuned server can have 1,000,000 open sockets at once. So, your CPU usage is going to be more about how many connections are being established and what are they asking the server to do every time they are established than it is about how many open (and mostly idle) connections there are.

Remember, every http connection has to create a TCP socket (which is roundtrips between client/server), then send the http request, then get the http response, then close the socket. That's a lot of roundtrips of data to do every minute. If the connection is https, it's even more work and roundtrips to establish the connection because of the crypto layer and endpoint certification. So doing all that every minute for hundreds of thousands of clients seems like a massive waste of resources and bandwidth when you could create one SSE connection and the client just listen for data to stream from the server over that connection.

As I said in our earlier comment exchange on a different question, these types of questions are not really answerable in the abstract. You have to have specific requirements of both client and server and a specific understanding of the data being delivered and how urgent it is on the client and therefore a specific polling interval and a specific scale in order to begin to do some calculations or test harnesses to evaluate which might be the more desirable way to do things. There are simply too many variables to come up with a purely hypothetical answer. You have to define a scenario and then analyze different implementations for that specific scenario.

Number of requests per second is only one of many possible variables. For example, if most the time you poll there's actually nothing new, then that gives even more of an advantage to the SSE case because it would have nothing to do at all (zero load on the server other than a little bit of memory used for an open socket most of the time) whereas the polling creates continual load, even when nothing to do.

The #1 advantage to server push (whether implement with SSE or webSocket) is that the server only has to do anything with the client when there is actually pertinent data to send to that specific client. All the rest of the time, the socket is just sitting there idle (perhaps occasionally on a long interval, sending a keep-alive).

The #1 disadvantage to polling is that there may be lots of times that the client is polling the server and the server has to expend resources to deal with the polling request only to inform that client that it has nothing new.

How can we calculate where is the limit frequency for Ajax or SSE?

It's a pretty complicated process. Lots of variables in a specific scenario need to be defined. It's not as simple as just requests/sec. Then, you have to decide what you're attempting to measure or evaluate and at what scale? "Server performance" is the only thing you mention, but that has to be completely defined and different factors such as CPU usage and memory usage have to be weighted into whatever you're measuring or calculating. Then, you may even need to run some test harnesses if the calculations don't yield an obvious answer or if the decision is so critical that you want to verify your calculations with real metrics.

It sounds like you're looking for an answer like "at greater than x requests/min, you should use polling instead of SSE" and I don't think there is an answer that simple. It depends upon far more things than requests/min or requests/sec.

What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet?

In the examples below the client is the browser and the server is the webserver hosting the website.

Before you can understand these technologies, you have to understand classic HTTP web traffic first.

Regular HTTP:

  1. A client requests a webpage from a server.
  2. The server calculates the response
  3. The server sends the response to the client.

HTTP

Ajax Polling:

  1. A client requests a webpage from a server using regular HTTP (see HTTP above).
  2. The client receives the requested webpage and executes the JavaScript on the page which requests a file from the server at regular intervals (e.g. 0.5 seconds).
  3. The server calculates each response and sends it back, just like normal HTTP traffic.

Ajax Polling

Ajax Long-Polling:

  1. A client requests a webpage from a server using regular HTTP (see HTTP above).
  2. The client receives the requested webpage and executes the JavaScript on the page which requests a file from the server.
  3. The server does not immediately respond with the requested information but waits until there's new information available.
  4. When there's new information available, the server responds with the new information.
  5. The client receives the new information and immediately sends another request to the server, re-starting the process.

Ajax Long-Polling

HTML5 Server Sent Events (SSE) / EventSource:

  1. A client requests a webpage from a server using regular HTTP (see HTTP above).
  2. The client receives the requested webpage and executes the JavaScript on the page which opens a connection to the server.
  3. The server sends an event to the client when there's new information available.

    • Real-time traffic from server to client, mostly that's what you'll need
    • You'll want to use a server that has an event loop
    • Connections with servers from other domains are only possible with correct CORS settings
    • If you want to read more, I found these very useful: (article), (article), (article), (tutorial).

HTML5 SSE

HTML5 Websockets:

  1. A client requests a webpage from a server using regular http (see HTTP above).
  2. The client receives the requested webpage and executes the JavaScript on the page which opens a connection with the server.
  3. The server and the client can now send each other messages when new data (on either side) is available.

    • Real-time traffic from the server to the client and from the client to the server
    • You'll want to use a server that has an event loop
    • With WebSockets it is possible to connect with a server from another domain.
    • It is also possible to use a third party hosted websocket server, for example Pusher or others. This way you'll only have to implement the client side, which is very easy!
    • If you want to read more, I found these very useful: (article), (article) (tutorial).

HTML5 WebSockets

Comet:

Comet is a collection of techniques prior to HTML5 which use streaming and long-polling to achieve real time applications. Read more on wikipedia or this article.


Now, which one of them should I use for a realtime app (that I need to
code). I have been hearing a lot about websockets (with socket.io [a
node.js library]) but why not PHP ?

You can use PHP with WebSockets, check out Ratchet.

Server client communication: Long Polling, Comet, & Server-sent Events (SSE)

This post is a better explanation, discussing the difference/advantages/etc, about Long Polling, Comet, SSE and WebSockets.

For the most part, the client usually has to make the first request to the server to establish a connection. Once a connection is established, then the server can push data to the client. So even with WebSockets, the client will make the initial request to the server for establishing a reliable connection between the two.

Server-Sent Events uses a normal HTTP GET request to establish a connection with the server. It's also a read-only connection for the client. It has the benefit of having an easy implementation since we don't have to define a new protocol. The issue is that HTTP connections, even as persistent-connections, are closed after around 15 seconds by most web servers. Even for long standing requests, the web server often has a timeout after which it closes the connection. This is where the idea of long polling comes in. It's a simple idea that we make a normal ajax request to the server and the server leaves it open for as long as possible. If the request is closed by the server for whatever reason, you immediately make the same request again. You can implement a long polling mechanism (ie. Comet) pretty easily with a server such as Node.js and a normal Ajax request from the browser. Server-Sent Events tries to abstract away the browser side implementation of this with EventSource. So instead of you having to implement the browser/client side code for long polling/comet, the browser handles this for you. It provides a nice abstraction of what seems like a persistent connection. Your web server just needs to look out for GET requests which specify the Content-Type, in the header, as "text/event-stream" and leave the HTTP connection open as long as possible.

I would suggest that you don't over complicate what Server-Sent Events are. If you understand a normal HTTP GET request, then you likely already have a 90% understand of the idea behind it.

There is one difference between SSE/Comet and traditional long polling that might be worth highlighting. From my experience, the idea behind long polling is that your request doesn't return until you have an update. At which point the HTTP connection is closed and another request is made immediately afterwards. With SSE, though you can close the HTTP connection right after you send the updated message, your aim is to flush the data from the server to the client without actually closing/ending the HTTP request. This avoids the overhead of actually making a GET request. This can be achieved with a regular ajax request, but again SSE provides a nice/efficient implementation with EventSource.

Edit: clarify distinction between SSE and long polling.

Server-Sent Events Polling causing long delays

Everything looks robust, so I'm going to take a guess that you are being hit by session locking. PHP sessions lock the session file, such that only one PHP script can use the session at a time; when you think about it, this is a great idea!

The problem with sessions and SSE is that the SSE PHP process runs forever, and therefore it locks the session forever. If any other PHP script tries to run with the same session, it will block (at the session_start() call, I believe).

This looks like a good article on the subject; the advice is to call session_write_close() once you know longer need the session. E.g. if you just need to use the session to check they have previously authorized themselves, then straight after that you call session_write_close(), and other processes will not get blocked.

What is the difference between Forever-frame and server sent events?

I'd not heard of Forever-frame by that name before! (It is covered in ch.7 of my book, Data Push Apps with HTML5 SSE, in the "iframe" section).

Long-polling: make a request (using XMLHttpRequest, i.e. ajax), keep it open until the data is ready on the server. Then the socket closes. Re-connect to get the next bit of data.

XHR polling: make a request (using XMLHttpRequest2, i.e. ajax), but listen in to the readyState==3 signals. The back-end server has to know to keep the connection open, and the client has to know to listen to readyState==3. (Does not work in IE9 and earlier, because that browser never delivers the readyState==3 messages, but goes straight to readyState==4)

iframe: open a hidden iframe to the back-end process. Regularly go look at the source code of the iframe, and see if anything new is there. (Technically it works on all browsers, but IE8 and IE9 were the only ones in my (2013) tests with low enough latency for the updates to be useful.)

SSE: An HTML5 standard that basically works like XHR polling (Firefox and Chrome, at least, implement it directly on top of XMLHttpRequest2), but with the complex details hidden from you. It also adds auto-reconnect if the socket goes down, and a few other high-level features like that.

At the end of chapter 7 of the afore-mentioned book, I show code to get all the techniques to work in just about any browser. The order of preference is:

  • SSE if available
  • else XHR if available
  • else iframe if IE8 or IE9
  • else longpoll

There is one other difference: the XHR and iframe techniques are storing the entire message history in memory. So, if you intend to keep the socket open for a long time and/or send a lot of large messages, this may cause a memory issue that wouldn't happen with SSE.

Executive Summary: Don't worry about "forever-frame" unless you have enough customers still using IE8/IE9 that the longpoll approach would create noticeable additional load on your infrastructure.

Web Socket vs Long Polling vs server-sent events for a cross-platform chat application?

WebSocket is built for applications such as this, while long polling (however well done) is a hack. Support for WebSocket is also very broad, and you can use e.g. a flash fallback in older browsers.
Server-sent-events are only part of a solution, and you have a big support gap in IE.
(Shameless promotion of an open source project I'm connected to: take a look at WAMP (http://wamp-proto.org) and Crossbar.io (http://crossbar.io), which offer communication patterns on top of WebSocket and provide a lot of infrastructure for building a chat application.)

HTML5 Server-Sent Events prototyping - ambiguous error and repeated polling?

The problem is your php.

With the way your php script is written, only one message is sent per execution. That's how it works if you access the php file directly, and that's how it works if you access the file with an EventSource. So in order to make your php script send multiple messages, you need a loop.

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

function sendMsg($id, $msg) {
echo "id: $id" . PHP_EOL;
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
while(true) {
$serverTime = time();
sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));
sleep(1);
}
?>

I have altered your code to include an infinite loop that waits 1 second after every message sent (following an example found here: Using server-sent events).

This type of loop is what I'm currently using and it eliminated the constant connection drop and reconnect every 3 seconds. However (and I've only tested this in chrome), the connections are now only kept alive for 30 seconds. I will be continuing to figure out why this is the case and I'll post a solution when I find one, but until then this should at least get you closer to your goal.

Hope that helps,

Edit:

In order to keep the connection open for ridiculously long times with php, you need to set the max_execution_time (Thanks to tomfumb for this). This can be accomplished in at least three ways:

  1. If you can alter your php.ini, change the value for "max_execution_time." This will allow all of your scripts to run for the time you specify though.
  2. In the script you wish to run for a long time, use the function ini_set(key, value), where key is 'max_execution_time' and value is the time in seconds you wish your script to run for.
  3. In the script you wish to run for a long time, use the function set_time_limit(n) where n is the number of seconds that you wish your script to run.


Related Topics



Leave a reply



Submit