13

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:

  • Socket.IO 0.9 degrades
  • Engine.IO enhances
  • Socket.IO 1.0 will use Engine.IO
  • If you want to run Engine.IO on multiple instances, you have to write the redis store yourself

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?

Community
  • 1
  • 1
bendytree
  • 13,095
  • 11
  • 75
  • 91
  • If you go with Engine.IO, yes you will have to write your own store. I know it's not cool to complain about lack of updates on open source projects, but I feel like they have dropped the ball on Socket.IO. There are many questions floating around like this and 1.0 has been just around the corner for over half a year now. There are hundreds of open issues that are many months old on socket.io so it gives all appearances of being unmaintained at this point. – Timothy Strimple Aug 13 '13 at 07:36
  • If you want to use engine.io then yeah you would have to write the extra stuff. I would imagine socket.io is facing some roadblocks adapting to the new core. Socket.io is to engine.io what express to connect. It hides the low-level details of engine.io and is flexible and user-friendly. But I would ask you not to build store on top of it, because of same reason. socket.io 1.0 was being built on promise of engine.io. Given the status of socket.io 1.0, can anyone guarantee engine.io would be success. If 1.0 is in pipeline wait for it, because it will be better than what you can do, if it comes. – user568109 Aug 14 '13 at 05:35

3 Answers3

10

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).

bendytree
  • 13,095
  • 11
  • 75
  • 91
  • Hey now that you switched from engine to sockjs does the redis pub/sub still work the same? You can still scale with redis? – Harry Aug 31 '13 at 04:58
  • 1
    To be clear, the Redis pub/sub isn't built into engineio or sockjs. I wired up redis completely independently. Since I'm using Primus, switching did not change the redis piece at all. – bendytree Aug 31 '13 at 19:42
  • Why not use Primus + Redis pub/sub and add SockJs layer? – hfcorriez Oct 15 '13 at 10:25
  • A single socket io client can send thousands of requests per second, why not simply make a time variable where you store when this socket last sent a request, and if it was less than a milli second ago for example then this socket is spamming and disconnect it. Or you know, any other custom check that does something similar to block spamming sockets and abusive users. Unless I misunderstood your problem with socket io... – Joe Yahchouchi Sep 10 '14 at 17:56
1

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

Deniz Ozger
  • 2,565
  • 23
  • 27
-1

Well, as you mentioned yourself, I should have a look at Primus. Scaling is achieved using HAProxy. As underlying communication you can still use Socket.io, but also engine.io. By using Primus, you can experiment with different libraries. There is an interesting article about scaling Redis at http://pusher.com/docs/server_libraries.

Kurt Pattyn
  • 2,758
  • 2
  • 30
  • 42
  • Keep in mind it's recommending HAProxy for its sticky sessions which means it should always redirect someone with the same session to the same machine. It does this in lieu of a common store for the connection information. There are some pros and cons to each approach so make sure you understand those before jumping deciding. http://stackoverflow.com/questions/1553645/pros-and-cons-of-sticky-session-session-affinity-load-blancing-strategy – Timothy Strimple Aug 13 '13 at 07:16
  • I did not decide. I was just trying to help and point the OP to some articles someone else wrote. Thanks for downgrading. – Kurt Pattyn Aug 13 '13 at 08:47
  • I know. That was meant for OP. – Timothy Strimple Aug 13 '13 at 15:26