IT IS HERE! Get Smashing Node.JS on Amazon Kindle today!
Show Posts
← Back to homepage

On Monday I had the pleasure of speaking once again at NodeConf in Portland. On this glorious second edition, several talks were dedicated to the topic of realtime, covering angles such as its inception and future, scalability, backend messaging and more.

Mikeal requested that I talk about the state of Socket.IO, now one of the corner stones of the so-called realtime web and one of the most popular JavaScript projects on GitHub at the time of writing. Those familiar with the project know that stability and reliability are the commanding goals of all the ongoing work towards 1.0.

These goals are largely attained by the introduction of a new library, whose first release was announced at the conference: Engine.IO.

What’s Engine.IO?

Engine.IO acts as a transport layer for the data exchanged by Socket.IO between a server and a browser. It does not replace Socket.IO. It simply abstracts out the inherent complexity of supporting realtime data exchange in multiple browsers, devices and networks.

It’s a smaller separate module (Node.JS server and browser client), which significantly improves:

  • maintainability
  • testing
  • multi-language and platform support (more on this later)
  • debugging and issue tracking
  • performance analysis and benchmarking

Engine.IO is designed to support techniques for communication with browsers like IE6, but we can hope for a future where the only transport layer that needs to be supported is WebSocket. For this reason, both the Engine.IO client and server share the same API as WebSocket:

The following browser code would only require the constructor change from eio.Server to WebSocket:

var socket = new eio.Server('ws://localhost');
socket.onopen = function(){};
socket.onmessage = function(ev){ alert(ev.data); });

The following echo server code would only require changing the require call from engine.io to websocket.io, my WebSocket server that supports all existing WebSocket specs:

var http = require('http').createServer();
var engine = require('engine.io').attach(http);
engine.on('connection', function (socket) {
  socket.on('message', function(msg){
    socket.send(msg);
  });
});

What’s better?

Engine.IO marks the transition between fallback-based connections to upgrade-based connections. What does this mean? Before, Socket.IO would perform feature detection to determine the best transport. In modern browsers, the response would normally be “WebSocket”.

As it turns out, however, feature detection in many cases would not correlate with an immediately successful connection. A number of things outside of the control of the browser would impede the usage of WebSocket as a transport:

  • outdated desktop antivirus or personal firewall solutions
  • proxies or firewalls either at the user network level (like offices or classrooms)
  • proxies at the cloud level (like Heroku’s lack of WebSocket support)

As it’s usually the case, the only way to diagnose problems like these at the client level is to rely on timeouts. Which means that we got so excited about using WebSocket that we made the user wait 10, 15, 20 seconds until we could fall back to a reliable transport: long-polling.

No one ever got fired for choosing
long-polling

One thing is known for certain. Long polling always works. What is lesser known to many, however, is that for the majority of communication purposes between a browser and a server over TCP connections long-polling is a fine transport.

It’s widely deployed, it’s been shown to scale and it even makes for fascinating realtime data visualizations. If you don’t believe me, try this Socket.IO example running on Heroku.

More tweets that you can possibly care about get retrieved in real-time.

Engine.IO ensures reliability and immediacy of connections by doing long-polling first, always. Meanwhile, it attempts to verify whether a successful WebSocket connection can be established on the side by attempting a simple packet probe. For older browsers, it can even lazy-load the Flash WebSocket client alternative, which keeps the client weight down.

In most scenarios, the upgrade from long-polling to WebSocket happens very fast and the best case scenario performance is accomplished. But the worst case scenario sees the most improvements, since we trade some speed in the data exchange in favor of no timeouts upon the initial connection.

Engine.IO also allows you to perform progressive enhancement at the application layer. You can listen on the upgrade event to know if the connection is WebSocket-based, and you could adapt the views accordingly.

What’s missing?

Realtime applications developed today need more features than simple data exchange. JSON encoding / decoding, custom events, automatic reconnection with exponential backoff and multiplexing are all features outside of the scope of Engine.IO that Socket.IO is in charge of. These will be performed with unprecedented reliability and stability thanks to this new division.

Over the next few months, I’ll continue my work with community members in charge of maintaining ports of Engine.IO and Socket.IO to other languages and platforms. Engine server ports to Go and Java are underway, and a Lua (Luvit) server and Java client are already readily available.

In the coming weeks the integration between Socket.IO and Engine.IO will be announced, along with the new website to keep track of this exciting and ever-expanding realtime universe.

17 Comments

Wes said

I’m trying to make sure I understand your article,

So if I understand correctly, the biggest impact of Engine,IO will be that it is upgrade-based rather than fallback-based?

Engine.IO is not meant to replace Socket.IO, but just abstract away the communication between client and server, correct?

Solomon said

awesome!!, i cnt wait for the real-time revolution to start!! lool

John McLear said

Hey Guillermo, Engine IO sounds like a reasonably sensible proposition. I’d love to see how you can hack it into Etherpad to try help us scale our larger deployments.

Christian Sanz said

This is great Guillermo! not having to worry about the transport depending on the device/browser type/version and assuring the data WILL get transfered is huge… just let Engineio manage all of it. Thanks!

Guillermo Rauch said

@Wes
That is all correct! Engine.IO becomes a “transport” of Socket.IO

CBuosi said

Nice article!

Kelly Miyashiro said

I’m very interested in the Java port, how soon do you think those will be done? A year or less?

DAddYE said

Love it! Thanks guys!

Arunoda Susiripala said

Great. Is there any possibility to try this now?

Guillermo Rauch said

@Arunoda

npm install engine.io

Grab the browser client from engine.io-client `dist/` directory.

Oleg Slobodskoi said

Please support long-polling without sticky sessions!

Arunoda Susiripala said

Seems like its a fork of Socket.IO – https://github.com/learnboost/engine.io

How about the roadmap of this?
* Is this maintain as a separate project?
* Any plans on integrating into Socket.IO

BTW: Please add/emphasis how to try this on the Blog Post

Alexandre Bourget said

Cool! Looking forward to port all of this to Python and expand the gevent-socketio module to support those new features.

Eugen Dück said

If you can use https though, I guess you won’t suffer from these firewall, proxy and antivirus software issues.

Guillermo Rauch said

There’s still be issues with intermediate proxies once the connection is decrypted on the server end (see: ELB on HTTP mode, Heroku, etc)

Rick Jafrate said

Guillermo,
Very interesting. I would like to correspond with you about integrating this into a current control system project consisting of robots, vision, motion control, etc.

The automation platform is Win7/x86 platform with a real-time extension. Future projects may use Linux instead of Win7. The real-time can communicate via TCP/IP. Is it possible for Engine.IO to interface to the real-time via TCP/IP? If so how?

Guillermo, please let me know what you think and how we can proceed. There may be some funding available for support/consulting.

Cheers
Rick

Your thoughts?

About Guillermo Rauch:

CTO and co-founder of LearnBoost / Cloudup (acquired by Automattic in 2013). Argentine living in SF.