Absolutely! I've had terrible experiences with vanilla socket.io regarding reconnections, performance, and reliability. This is even after the 1.0 release.
Lately, I've been using primus [1], which is an API unification layer for socket.io, sockjs, faye, and native websockets. Swapping one engine for another is trivial, and they've taken pains to abstract a core subset of functionality.
Agreed. Mostly quoting myself from earlier this year: I don't normally like bashing open-source projects, but socket.io should not be used. It may be noob-friendly, but that's just because it does things so automatically that you can't really use it correctly. When I was a websockets noob, I used socket.io briefly, and it was a complete waste of time.
SockJS is much better, as is raw websockets. Presumably Primus, too, although I'm a bit surprised that one can come up with a sensible interface that can be layered over both Socket.io and anything else.
+1 for Primus. We moved to it on BitMEX from a custom SockJS + Mux-demux setup and the transition was painless. We now get the ability to change transports based on client (so our API clients get the very fast standards-compliant node `ws` library, while browser clients get engine.io). We also gained reliable heartbeating which was a big win.
I've found the devteam to be really responsive and their choices of abstractions appear to work well.
I moved to SockJS [1].
Socket.io itself was great but I had serious trouble to get socket.io server (gevent-socketio) working with Python and Flask.
SockJS has a decent JS client-lib and a good set of server counterparts. Node, python, erlang and java (using Vert.x).
Vert.x [1] combined with SockJS is especially powerful -- vert.x supports so called 'verticles' in multiple languages (JavaScript, Ruby, Java etc) that are running as tiny servers who can communicate over eventbus. Then the SockJS lib can be used to handle communication between the browser and Vert.x eventbus.
Probably not intended but I'm also using SockJS to communicate events between a Flask app in python and Vert.x java verticle.
We use ws(https://github.com/websockets/ws) in prod. Clean, fast, and simple. Plus it supports browsify using native implementation but wraps it to fit the server side api.
SockJS is definitely a reasonable choice as a base. At Pusher we use a fork of SockJS for HTTP fallback but we actually use em-websocket [1] (ruby) for our WebSocket API. Given the opportunity we'd probably move away from SockJS to something much simpler because we only want the HTTP fallback part and it only handles < 8% of our connections.
If you _only_ want WebSocket connections with no HTTP fallback then Faye WebSocket [2] may be an option. But any production application is going to require fallback for older browsers and pesky proxies/firewalls.
Faye [3] is solid (obviously used Faye WebSocket), has implementations in Node and Ruby, but is a PubSub solution. I'd kinda argue that any real-time app needs at least PubSub functionality anyway.
The ws Node module [4] is apparently "The fastest RFC-6455 WebSocket implementation for Node.js" and receives contributions from 3rd-Eden who is also behind Primus [5]. But it's also WebSocket with no fallback.
I haven't used Primus, but I really like the idea of offering a layer above the underlying connection engine. I've seen contributions to Socket.IO dip in the past (prior to CloudUp being acquired by Automattic), but Socket.IO is used by so many apps that somebody is always likely to maintain it for the foreseeable future. I'm generally in favour of adding abstractions around layers like this (connectivity, DBs, Message Queues, Hosted Services etc.). However, in this case you're then adding a dependency on Primus. Isn't software fun!
We're lucky in that we require web workers, so we get web sockets compliance for free. We also are an infrastructure deployment, so we get some leeway in ignoring shitty devices.
I made the decision early on to push on the business side as hard as possible to only use modern web tech, and it has saved us a lot of trouble. HTML5, without compromise, is nice.
Lucky indeed! I've been pushing for us to drop IE7 (and maybe 8) so we can move to more modern tooling and libraries as part of the development process. But customer requirements mean we've got to stick to IE7 for now.
What's great about SockJS is it's meant as a WebSocket polyfill and nothing more. It also has some semblance of a protocol definition. This makes it an ideal foundation to build upon if what you really want is WebSockets, but you need a bandage for old browsers.
Meteor notably uses SockJS as part of their DDP spec.
Also Pushpin includes a SockJS to native WebSocket translator.
It does seem to be the most commonly used WebSocket polyfill around. We also use web-socket-js [1] for fallback. But Version 3.0 of pusher-js [2] will remove that.
One negative with SockJS has been the complexity of the fallback approach on the client (the browser). Especially when it's only for 8% of connections. A single simple cross-browser HTTP-based transport would remove the code complexity and reduce the file size.
The problem is that even if XHR is on a local domain and ensured to work, long-polling is still more intensive than, for example a persistant frame, because you have to re-establish a new connection after each message, even if you bundle messages to a one second window, it's still got the overhead of a new connection (and the latency involved therin) which is even longer if HTTP2/SPDY + SSL.
Of course, that may well be enough for some situations, for others, there's too many server-pushed messages to keep up with that model as well.
The overhead of long-polling isn't quite so bad in practice thanks to persistent HTTP connections, where an existing TCP connection is reused for future HTTP requests. Pretty much all browsers support this, and so a re-poll is usually 1 packet.
Of course, long-polling is still more overhead than a streaming connection.
I switched to Faye (http://faye.jcoglan.com/) an implementation of Bayeux protocol programmed by James Coglan.
I'm using the node version of the library in my games for 4 years with excellents results.
I use [ws](https://github.com/websockets/ws). I've never had any trouble with it, and it benchmarks well. Of course, there's no fallback there; just websockets.
I haven't seen a websocket+fallback lib that seems like it will work well. Requiring sticky sessions and disallowing using node's cluster module is the norm, and neither of those are appealing. We've rolled our own polling fallback, which is also used to cleanly handle missed messages during a websocket reconnect.
Is it documented anywhere how they handle TURN/ICE/STURN for dealing with firewalls and routers?
EDIT: Looks like it doesn't. This is basically just a very small library on top of socket.io. Look forward to them helping solve the TURN/ICE/STUN issues :(
Too bad the demo doesn't work, I was really excited for this. Regardless, big congratulations to the Socket.IO team for an awesome feature! And props to Feross for his simple-peer module, he is doing incredible work in the WebRTC world.
In other news, to address some of the comments here:
- As others have mentioned, https://github.com/sockjs is an alternative that is more lean with less features.
- I've also written an inverse websocket tool that behaves like a regular HTTP request/response, but will proxy it through WebSockets or fallback to JSONP. I really like this approach because it feels more RESTful, has less overhead, and even allows the browser to do a `createServer`. It is currently pretty tightly coupled into a project of mine (next bullet), I'll try pulling it out into its own library if there is demand, but here is the source:
- If you do use the P2P Socket.IO feature, the next thing you'll need is a P2P database that can run in the browser! And that is what my main open source project, http://gunDB.io/ is about. The previous bullet's code is my nimble websocket and fallback library I wrote for this project, and that is why they are currently tightly coupled - sorry about that. If there is enough demand for it by itself then I'll try making it into its own library.
Does anybody have a small, fast, no-bullshit, modern websockets library they'd nominate for use with node?