Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make use of redis pub-sub for improved performance #46

Merged
merged 3 commits into from
Feb 14, 2015

Conversation

koszta
Copy link

@koszta koszta commented Dec 8, 2014

Previously socket.io-redis was listening for the whole pattern socket.io#* and the messages were sent to socket.io#id. This means that all the socket.io servers will receive all messages, even if the server does not use that namespace, even if there are no client listening to any of those rooms on them. If there are some nodes which send a lot of message, all the socket.io servers will have 100% cpu really quickly.

I changed it to use socket.io#namespace#room in order to be able to filter the messages on the redis server already, so the socket.io servers will receive only the messages they need to receive.

@peteruithoven
Copy link

Nice! hopefully this solves #41

@koszta
Copy link
Author

koszta commented Dec 9, 2014

Created a small repo to test this issue
https://github.com/koszta/socket.io-perf

@koszta koszta mentioned this pull request Dec 10, 2014
@nkzawa nkzawa added the enhancement New feature or request label Dec 26, 2014
@nkzawa
Copy link
Contributor

nkzawa commented Dec 26, 2014

Thank you for your PR! I think socket.io#namespace#room is great to fix the issue, but I don't get why we have to fix add, del and delAll too.

@koszta
Copy link
Author

koszta commented Dec 26, 2014

We can listen for the entire socket.io#namespace#* pattern or for the only necessary channels, such as socket.io#namespace and for all the rooms socket.io#namespace#room. The latter needs add, del, delAll. Upon a client joins a room, we need to listen for the room's channel, when all client left a room or disconnected, we can stop listening for the channel, so there is no 'channel leaking', no need to discard messages.

@nkzawa
Copy link
Contributor

nkzawa commented Dec 27, 2014

anyway implementations of add, del looks wrong for me.

@nkzawa
Copy link
Contributor

nkzawa commented Dec 27, 2014

sorry, it looks correct. i was misunderstanding the redis client, will check again later.


next();
}, function(err) {
if (err) self.emit('error', err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You move on even if there's an err. Add return.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And also pass it to the callback?

@objectiveSee
Copy link
Contributor

We can actually verify that this PR is needed. In the attached graph we have 3 instances on the same redis-adapter. The green and yellow ones are getting 50% traffic each, while the blue one is getting 0%. The high CPU on the blue instances shows there is a high base-line CPU for non-active nodes. Looking forward to this! Thanks @koszta

screen shot 2015-02-14 at 1 40 35 pm

@rauchg rauchg merged commit 278da75 into socketio:master Feb 14, 2015
@rauchg
Copy link
Contributor

rauchg commented Feb 14, 2015

Guys, I merged and applies changes of my own. @koszta you are the man. Can you take a look at index.js to see if everything looks good? Your tests do pass perfectly.

@koszta
Copy link
Author

koszta commented Feb 15, 2015

I checked it out. Everything looks good! Lots of improvements to my code. :) Thanks for everyone who tested this or contributed to it!

@bevacqua
Copy link

@rauchg could you bump the package version on npm?

@objectiveSee
Copy link
Contributor

We just deployed our upgrade to version 0.2.0 to production with this PR, and it fixed EVERYTHING! Immediately seeing a huge drop in CPU across our multiple servers, and our auto-scaling groups now can handle more sockets before needing to scale up. Thank you @koszta ! 💯 ❗ 💥

@rauchg
Copy link
Contributor

rauchg commented Dec 7, 2015

@objectivSee thanks for the amazing feedback! This is what we live for ❤️ 💓 ❤️
Thanks @koszta!

darrachequesne added a commit to darrachequesne/socket.io-redis that referenced this pull request May 10, 2017
This follows socketio#46. Each node will now listen to only three channels:

- `socket.io#<namespace>#*`: used when broadcasting
- `socket.io-request#<namespace>#`: used for requesting information (ex: get every room in the cluster)
- `socket.io-response#<namespace>#`: used for responding to requests

We keep the benefits of socketio#46 since:

- messages from other namespaces are ignored
- when emitting to a single room, the message is sent to
  `socket.io#<namespace>#<my-room>`, so listeners can check whether they
  have the room before unpacking the message (which is CPU consuming).

But there is no need to subscribe / unsubscribe every time a socket
joins or leaves a room (which is also CPU consuming when there are
thousands of subscriptions).
darrachequesne added a commit to darrachequesne/socket.io-redis that referenced this pull request May 10, 2017
This follows socketio#46. Each node will now listen to only three channels:

- `socket.io#<namespace>#*`: used when broadcasting
- `socket.io-request#<namespace>#`: used for requesting information (ex: get every room in the cluster)
- `socket.io-response#<namespace>#`: used for responding to requests

We keep the benefits of socketio#46 since:

- messages from other namespaces are ignored
- when emitting to a single room, the message is sent to
  `socket.io#<namespace>#<my-room>`, so listeners can check whether they
  have the room before unpacking the message (which is CPU consuming).

But there is no need to subscribe / unsubscribe every time a socket
joins or leaves a room (which is also CPU consuming when there are
thousands of subscriptions).
darrachequesne added a commit that referenced this pull request May 10, 2017
This follows #46. Each node will now listen to only three channels:

- `socket.io#<namespace>#*`: used when broadcasting
- `socket.io-request#<namespace>#`: used for requesting information (ex: get every room in the cluster)
- `socket.io-response#<namespace>#`: used for responding to requests

We keep the benefits of #46 since:

- messages from other namespaces are ignored
- when emitting to a single room, the message is sent to
  `socket.io#<namespace>#<my-room>`, so listeners can check whether they
  have the room before unpacking the message (which is CPU consuming).

But there is no need to subscribe / unsubscribe every time a socket
joins or leaves a room (which is also CPU consuming when there are
thousands of subscriptions).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants