There’s been a lot of talk lately about realtime web and WebSockets, but did you know that there exists an alternative HTML5 technology called EventSource that could handle some of the scenarios as well? EventSource is also called Server-Sent Events (SSE), a name that I prefer to use in order to avoid confusion with the larger architectural pattern called event sourcing.
The three things you should know about Server-Sent Events are: It’s..
- uni-directional (only server push, initiated by client)
- using pure HTTP
- not using polling
The uni-directional constraint is not a problem, since the client still can GET data from the server or POST messages to the server, using XMLHttpRequest. Instead, let’s focus on the other two…
This feature is golden, because it has a lot of nice implications. First, even if SSE is not supported by all browsers, the fallback is just to start to use polling (polyfills for SSE are found here). Second, the integration story for other types of clients than browsers is better than websockets – no need for an websocket implementation on the client to be able to consume the events, just use HTTP. Third, it’s not an “all-or-nothing” approach like websockets – you can start with a naive server implementation and gradually improve it. I will explain this last statement in more detail below.
It’s not polling
Searching the web, it’s not a problem to find out how the data format for SSE looks like. I recommend to read the last part of section 7 of the specification for more details. However, it’s not clear how the connection between the client and the server is working. At first, I thought I just had bad luck in searching the net, but now I realize why there was not a single answer on how to think about the client/server connection. The answer? There is not one right answer, but rather several right answers, depending on your requirements.
First, let’s look at a sequence diagram using as much of SSE’s promises as possible. (The image is a link to a larger version)
In the diagram, we see that a connection is kept open as long as possible by the client/server pair and when the connection is closed (i.e. by a router, proxy, firewall, etc) the client reconnects to the server. As Damien Edward says on the excellent Hanselminutes episode about realtime web (I’m paraphrasing): SSE is similar to the long polling strategy, except that the connection is kept open as long as possible.
Keeping a connection opened as long as possible? That doesn’t scale! Yes and no. As Damien Edwards mentions in the Hanselminutes episode, in classical usage of ASP.NET this would be a problem, since every connection has a thread in the thread pool. If performance becomes a problem, one can refactor towards an asynchronous model, à la Node.js, which would reduce the memory footprint. But not every developer groks asynchronous design well, so there’s cost involved here as well. Of course, it depends a lot on your specific scenario, YMMV.
But there exists a still simpler solution: instead of keeping the connection open you can close it when you consider yourself done.
“Ahaha, that’s polling!” Yep, it is, and it’s very simple to implement and understand. And it has some potential problems, of course, but it all depends on what your scenario is. Perhaps it’s a sufficient design to use polling, both for user experience and performance?
A cool thing with SSE is that you can perform these refactorings on the server-side without changing the client side. “Upgrading” websockets in a similar way is not possible – either you use a websocket connection or you don’t. But then, if you know that [parts of] your web app is going to need “as much realtime as possible” and is expected to be used by many users at the same time, go for websockets.
There’s also an interesting possibility to use a more heterogeneous architectural style and use SSE on some parts of the app and websockets on other parts, depending on the scenarios and requirements.
Server-Sent Events is an interesting light-weight and refactoring friendly alternative to websockets and is worth investigating. It has a good 3rd party integration compared to websockets since SSE is using plain HTTP. And SSE is uni-directional, so the client needs to use XMLHttpRequest to communicate client-to-server.
W3C EventSource/Server-Sent Events Specification
When can I use Server-sent DOM events?
Damian Edwards explains The Realtime Web for ASP.NET with SignalR (audio podcast, recommended)
Real Time Rack (video presentation, recommended, start from 22:50 for non-Ruby content)
HTML5 Rocks: Stream Updates with Server-Sent Events
Aslak Hellesøy compares WebSockets and Server-Sent Events and concludes that SSE have a better application-to-application integration story
StackOverflow: WebSockets vs. Server-Sent events/EventSource
StackOverflow: What so different about Node.js’s event-driven? Can’t we do that in ASP.NET’s HttpAsyncHandler?
Jim Webber’s opinion about websockets
InfoQ: WebSockets versus REST