What is Server-Sent Events?

After discussing with plenty of developers during the last few months, I have realized that a huge portion of them don’t know what “Server-Sent events” (or “SSE”, or “EventSource”) is. My objective here is to give you all the information you may need about Server-Sent Events. And the first one is…

Why should you even learn anything about SSE?

As the economy and your users are more and more realtime oriented, you need Server-Sent Events if displaying the last data updates to your users may change their actions. The data itself doesn’t need to change very often, but when it does change, you really want users to know it!

Let’s look at some cases, before we start explaining the technical details:

  •  users may click on the last news available rather then shutting down the page.
  • Services/product availability. If you sell products or service that are rare for this specific client (car-sharing, docks for bike-sharing, promotions with limited stocks, …), you want to make sure your prospect knows it is available as soon as possible.
  • Prices
  • Social / chat… no need to explain!
  • You may just want to display rapidly changing data: game score, trading, dashboard, …

“I don’t care about your “Server-Sent stuff”, I have WebSockets!”

Ok, WebSockets are trendy, fast and quite easy to implement now, but 1) It means you already understood that you need something better than HTTP Polling. Good! 2) There are pros/cons for WebsSocket and SSE. I suggest you read this blog post (http://streamdata.io/blog/push-sse-vs-websockets/ ) and come back here afterwards… I will be waiting for you…

waiting

If you are lazy, here is a very short summary. WebSockets are bilateral (you don’t always need bi-direction), not HTTP (some proxy won’t let it go through) “protocol” without standards for error handling. SSE is mono-directional (server to client), HTTP protocol with error handling standards. Both improve hugely latency for users. For a server load point of view, we achieved better performance with SSE than WebSockets (higher number of final users handled by one server).

“I don’t care about your “Server-Sent stuff”, I will request every half a second!”

… now we need to explain a little bit more what Server-Sent Events is.

So what is Server-Sent Events?

A client subscribes to a “stream” from a server and the server will send messages (“event-stream”) to the client until the server or the client closes the stream. It is up to the server to decide when and what to send the client, for instance as soon as data changes.

To fully understand SSE, we need to explain polling. The “historical” method of receiving information is to ask for it. The good old “request/response” paradigm! When you poll, the client side asks for information and server gives back the information available. No way to get something without asking it. With AJAX, you can make the polling to happen a pre-defined frequency.

(To optimize server load and bandwidth, you could decide that the server answers “No content” if the content has not changed since last client request … but it means your API is not RESTful anymore… :( ).

 

Comparing polling, long-polling & SSE messages for realtime updates

poll vs longpolling vs SSE

 

 

Well,  there are 5 major consequences of this ongoing polling:

  • You will overcharge the server load. It is hard to make benchmarks comparing SSE and “machine-gun” polling because it is obviously depending of the frequency of polling, data itself, the server configuration, etc. When we compared different scenarios, we ended up with a factor of 3 to 10: one SSE server can handle 3 to 10 times more users than a polling server (with the same objectives of latency).
  • You will over-load networks with useless data because the polling will send data even if they didn’t change! Very bad for the server-side and client-side costs and very bad for the planet (this one is maybe why I am writing this blog post! Did you know the web environmental footprint is equivalent to 40 nuclear plants in energy consumption and the whole civil flight in greenhouse gas?). Again, benchmarking polling versus streaming depends on the dataset, but we have test it on various public APIs, and the gain varies from 20% (all data are changing very often, we are just saving headers & round-trips) to 95% (Small part of the dataset are changing not that often).
  • Pushing consumes 75% to 95% less end-user battery than polling (here is the study)… don’t you want your user to keep on using your app?
  • Polling requiring 3 round-trips (TCP SIN, SSL and Data). In 3G, one round-trip takes 150 ms. So one polling will need 450 ms before the mobile receive any useful data. Once the connection is set with SSE, new data will be received by the mobile in 75ms (as data are directly sent from the server to the client).
  • Last but not least: you won’t be proud of your code!

The short summary; polling to display realtime data feels like this:

d7IwYq1 2

With Long-Polling (Hanging GET / COMET), the server will wait for a change of data before sending the response. The server will “hold” the request until it makes sense to send something. It might look attractive because you will alleviate of useless responses, but it requires hacks (such as appending script tags to an ‘infinite’ iframe) and server loads which are still huge. Moreover, how do you handle “up-dates” queuing, missed messages and disconnections?

icky

So why won’t you use a W3C standard built for realtime downstream?

We will first have a look on the messages themselves, then client-side implementation, and finally server-side one.

Event-stream

(the cool name for Server-Sent Events messages)

The event-stream is a simple stream of text data which must be encoded using UTF-8. Messages in the event-stream are separated by a pair of newline characters (“\n”).

The following field names are defined in the specification:

Event: The event’s type. It will allow you to use the same stream for different contents. A client can decide to “listen” only to one type of event or to interpret differently each event type.

Data: The data field for the message. You can put consecutive “data” lines.

ID: ID for each event-stream. Useful to track lost messages.

Retry: The time to use before the browser attempts a new connection after all connections are lost (in milliseconds). The reconnection process is automatic and is set by default at 3 seconds. During this reconnection process, the last ID received will be automatically sent to the server … … something you would need to code by yourself with Websockets or Long-polling.

cool

“:” : if you start the message by colon, it will be considered as comments

Some examples

data: hello word\n\n
data:  first line\n
data: second line\n\n 
id: 12345
event: newuser
data: {user name :  JohnDoe}\n
data: {user name : JohnDoe2}\n\n 

And yes, you can easily send JSON format without breaking the synthax! And that is a very very good news!

id: 12345
event: newuser
data: { \n
data: first name : John, \n
data: last name : Doe \n
data: }\n\n

Client Side

Browsers

Since Server-Sent Events is a W3C standard defining a Web-based API, the client side for web is quite simple and direct.

Here is an example taken from http://html5doctor.com/server-sent-events/. It handles connection to the server, listening to messages and handling of those messages.

var source = new EventSource('/stats');

source.onopen = function() {
   connectionOpen(true);
};
source.onerror = function () {
  connectionOpen(false);
};

source.addEventListener('connections', updateConnections, false);
source.addEventListener('requests', updateRequests, false);
source.addEventListener('uptime', updateUptime, false);

source.onmessage = function (event) {
  // a message without a type was fired
};

One problem is that all browsers do not support EventSource
Capture d’écran 2015-09-08 à 13.40.43
Source: http://caniuse.com/#search=Server-sent

So you will have to test if your user browser supports SSE


if(typeof(EventSource) !== “undefined”) {
      //Yeah … SSE supported!
} else {
      //wtf! Let’s make a polyfill
}

If the browser does not support SSE, you can use a polyfill. We have tested several ones available in GitHub and have decided to use this one for our own SDKs: https://github.com/amvtek/

For more code samples, you can check our own SDK or demos (quizz with D3.js, display of financial data)

Mobile apps

For mobile apps, there is no standard API. Things are a little bit more complicated, so my best option is to give links to libraries and some other blog posts detailing code sample.

Android

A simple app based on SSE on GitHub

An app using Server-sent events to get data from GitHub API

iOS

An app using Server-sent events to get data from the NewYork Times API

Conclusion

We advocate the use of high standards, and we believe each individual (surprisingly it includes developers) should think twice before consuming unneeded resources. When an app/website needs some data updated in realtime,  and there is not a need for upward data flow, Server-Sent Events should be considered first.  If you disagree, please comment on this article below, and we will happily reply.

I hope this article helped you. Enjoy your code.

Share it :
1000

Give it a try!

Try streaming any JSON REST API within 30 sec
curl -v "https://proxy.streamdata.io/http://mysite.com/myJsonRestService?param1=[]&param2=[]"

Leave a Reply

Your email address will not be published. Required fields are marked *