There are a few questions on this topic, but none quite address the issue.
I'm using Socket.IO with a redis-store and I'm prepping for a bump in traffic. My hosting company said, "You need to use Engine.IO instead of Socket.IO because it's way more efficient" so I'm scrambling to figure out what that means.
Questions like this have seemingly conflicting answers:
So the way I see it:
But then Engine.IO says it's "load balancer friendly" but says nothing about redis. It must have some kind of outside store, right? But if it has multiple transports and a store, what's the point of Socket.IO?
Then I see that Socket.IO might be abandoned and high profile companies are moving to Primus.
How do I go about scaling Engine.IO? Do I have to write the store myself?
Just wanted to share what I've learned in the last week, but hopefully someone else comes along and answers this definitively so I can give them a check.
1) Never use Socket.IO (as of 0.9.16)
My host was right to tell me to use Engine.IO (or anything else). Socket.IO has a huge number of major issues, the worst of which is that it will unexpectedly DDoS your server. I experienced this first hand with relatively few clients and it completely disabled my server until I could rewrite off Socket.IO. I scaled to 25+ drones to absorb the blow and it didn't matter. A single client can send 1000's of requests per second.
2) Other Engines Don't Have Redis Stores
Socket.IO lets you broadcasts across nodes by dropping in their Redis store. So far as I can tell, Engine.IO, Primus, and SockJS don't offer this. So when these engines claim "load balancer" friendly, it doesn't mean you can broadcast across nodes. I'm starting to think this is actually a good thing. Writing pub/sub with redis is relatively easy and having it separated out has been nice.
I ended up using Primus with Engine.IO, then used redis pub/sub to share events between nodes. It took me about 5 hours to remove Socket.IO, wire up Primus, write the pub/sub, and go live. So far it's been a much better experience.
UPDATE:
Ends up Engine.IO also gets in reconnect loops (a few per second), so I ultimately used SockJS. It's given me the best connectivity & stability, and Primus now handles the reconnect (which SockJS doesn't do).
I agree that Socket.IO should be avoided until v1.0 is released, it's buggy and in my tests Engine.IO performed better (https://medium.com/node-js-javascript/b63bfca0539). Primus is definitely a good option too: maybe you'll use Engine.IO now but when Socket.IO 1.0 is released you'll want to switch to it.
I implemented a similar program with Engine.IO and Redis and Pub/Sub structure, it looks very elegant. The below code subscribes a connected client to a room/channel.
io.on('connection', function (socket) {
var observerRedisClient = redis.createClient();
observerRedisClient.subscribe(resourceId, redis.print);
observerRedisClient.on('message', function(channel, message) {
socket.send(message);
});
});
And if you update that channel, ie. save some data and publish, then all subscribed clients will receive it.
redisClient.set(key, value, redis.print);
redisClient.publish(key, value);
If you are interested the code is open source: https://github.com/denizozger/node-engine.io-server
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With