WebSocket Fallbacks

by Subbu Allamaraju on November 16, 2011 · 2 comments

For a soon-to-open sourced nodejs based platform that I have been working on since June this year, I needed a way to send some optional telemetry data back to the browser without mixing it with the real data that the client code is interested in. The first thing I looked at was socket.io. Socket.io’s claim to fame is that it aims to “make real-time apps possible in every browser and mobile device”. But it comes at certain cost that may not be apparent. Since then I gave up on socket.io and switched to the plain WebSocket API on the client side and WebSocket-Node on the server. Here is why.

Cross browser WebSocket fallback is a fallacy. Such fallbacks exist because WebSocket support in browsers continues to limp and the spec itself is not done yet. Interoperability among browsers is not yet possible due to lack of protocol parity. For instance, about a month ago, I had to forego supporting Safari in favor of better experience in latest versions of Chrome and Firefox. But what’s wrong with fallbacks?

WebSocket interactions are bound to a connection – once the client opens a TCP connection, it can send and receive several messages using the WebSocket API. But with fallback approaches that rely on JSONP, XHR and iframes, clients and servers use HTTP for serializing messages.

Therein lies a key difference. With the WebSocket protocol, you can scope any state for the duration of the connection and remain state free across connections. For instance if you want to send some events as they occur to the browser, you can associate the subscription state with the socket. You don’t need to replicate that subscription state across all the server nodes that are serving WebSocket traffic. This makes horizontal scalability possible.

Not so with HTTP based fallbacks where every message could potentially come in over a different TCP connection. To account for this you either need to pin the client to a given node so that the same node handles all connections from a client, or replicate state across all the nodes serving the HTTP traffic. socket.io does the latter by using Redis. Consequently you end up trading off reliability and/or scalability.

This leads to my next point – if scalability is your concern, graceful degradation may just be sufficient in a lot of use cases. You can use feature detection in browsers to decide whether to use WebSocket protocol or not. Here is a simple approach I now use on the client side.

This helps me offer a degraded user experience when WebSocket support is not available, and I don’t have to introduce shared state on the server.

{ 1 comment… read it below or add one }

Alessandro Nadalin November 16, 2011 at 8:20 am

Can I haz highlight?
https://gist.github.com/1370310

:)

Reply

Leave a Comment

Previous post:

Next post: