I want to use socket.io, but I'll be running multiple instances of my app, so that's where things get interesting.
I need to run multiple instances on different ports. No problem here.
I decided not to use Node's own cluster, I'll use Nginx for load balancing (that's why I create multiple instances of the app). Nginx supports websockets, so this one is also sorted out.
Given that there'll be multiple instances, not all of them can't talk to each other directly (user A connects to instance X, if user B is connected to instance Y, they can't communicate since servers are independent from each other), so I need to use Redis' pub/sub mechanism as a wrapper in order to mimick socketio's emit & broadcast functionality. This way even if I have multiple instances of an app or run it on different servers, everybody will be able to talk to each other as long as they're connected to the same Redis server. To achieve this, I'll need to use socket.io-redis and socket.io-emitter modules.
Have I got that right, is there something wrong with this approach?
Sounds about right probably except are you sure you need multiple instances of your Node app on different ports? Because you might be able to handle more load than you would assume with one server and there are ways to separate out different communications channels with socket.io.
Related
I use Redis because it allows me to scale my applications horizontally (multiple servers). By using it's pub sub features all my servers can communicate with each other without needing to share memory.
So far, cool! We can add more nodejs servers, BUT all this servers subscribe to one single Redis server. So we have the situation in which we have many NodeJs servers communication to just one Redis server, we can serve more clients but still we have one Redis.
From my tests the Redis server uses less resources so can handle more, but still in this design I think is a SPF. What do you think?
What are the best ways to design a scalable system? I know about master/slave Redis but still I am not convinced if it is the best solution.
Yes, Redis is a single point of failure in what you describe. Not only in a sense that when it is down then your app is down, but also in the sense that if one of your processes remove or corrupt the data then it is lost forever.
What you can do is use multiple Redis servers and have a good backup strategy.
See this tutorial for clustering:
https://redis.io/topics/cluster-tutorial
See these tutorials for backups:
http://zdk.blinkenshell.org/redis-backup-and-restore/
https://redis.io/topics/persistence
https://www.digitalocean.com/community/tutorials/how-to-back-up-and-restore-your-redis-data-on-ubuntu-14-04
I'm looking for something to make my 2 running apps to communicate with each other.
I have two apps - main.js and events.js and I want to send event from events.js to main.js. I don't even know what to google for that coz everything I can find seems a little bit outdated and I'm looking something different then redis. I found out I can use uuid to communicate between different node.js processes but I don't know how. Any information would be great!
Your best bet is to use a message queue system similar to Kue.
This way you will be able to make your apps communicate to each other even if they are on different servers.
If you want to work without the redis backend you can skip the filesystem entirely and move to Sockets/TCP communication, which is one of the ways of getting around semaphores. This is a common method of low latency communication used by applications on the same machine or across the network. I have seen and used this method in games as well as desktop/server applications.
Depending on how far down the rabbit hole you want to go there are a number of useful guides about this. The Node.js TCP API is actually pretty great.
Ex.
https://www.hacksparrow.com/tcp-socket-programming-in-node-js.html
I am looking to implement some sort of chat server. And I want it to scale. This seems like a big question, so I guess I expect the answers to be direction pointers, sort of exploratory.
The end-user clients are web or phone client. I think some sort of websocket implementation, such as Socket.IO is nice.
On the server side I wish to use Node.js. I want the architecture to be scalable so that the number of users are not limited (well, within reason, the chance of big hit is not expected, and if it is, the chance of having smarter, experienced people to work on it is reasonable instead of currently just me coding) The number of users per chatroom is hopefully not limited, or maybe some fixed large number. And that means I need to scale horizontally using several servers written in Node.
Suppose some load balancer (and hopefully in the future not a single point of failure, but I don't know how I would achieve that, or maybe just move to AWS) are dispatching SocketIO connections from the end clients to the chat servers. Different users connection to different servers may be in the same room, so the messages need to be send to other servers.
How would I feasibly implement something like this? Hopefully not too complex.
Questions:
(1) If all servers need to handle all messages as users can be logged on via any of the servers, does this scale?
(2) Do I need some sort of message queue for the servers to talk among them? Is Pub-sub from Rabbitmq usable for this? Or if zeromq, how would I scale with pub sub? The Zeromq guide is has explanations for scaling to more than one server with REQ/REP type of applications. But not Pub Sub.
(3) Or should I start with XMPP?
I am hoping to make it work as easy as possible.
There's a rather good explanation at the Socket.io site. Have a look at
http://socket.io/docs/using-multiple-nodes/
It suggests using Nginx as HTTP load balancer, Node.js clustering (with sticky sessions) and Redis as the message backend.
I think your goals should be achievable with little to none coding involved, only using the given modules and configuration mechanisms.
I'm currently writing an application which has sockets engine running on one node.js instance and restful API for various resources on other. I'm wondering what could be the best way (performance wise) to communicate between these to instances if they would be located on a different servers. I don't want to duplicate data access logic on different instances and I want to keep everything (what's related to data access) in one place.
I thought about using simple HTTP API where sockets engine would make request to resources instance and get what it asked for but I'm not sure if I won't hit any performance bumps. In fact I could actually connect straight to mongodb and get the data that I want from there without making a request to other service but I feel like it would be nice to isolate data so that could be only used by resources instance and that would be the only application that uses mongodb instance.
Is there any other better ways to achieve something similar?
I want to scale my Node.js Socket application vertically and horizontally and I haven´t found a sophisticated solution yet.
My application has two use-cases:
Broadcast messages from one user to all others
Push messages from one user to a subset of users
On one hand, I´ve read that I need Redis for both cases together with socket.io-redis
On the other hand, I´ve watched this video and read this SO answer where it says that Redis isn´t reliable and it´s not guaranteed that the published messages will arrive, so you should only use it for clustering/vertical scaling
Microsoft Azures solution to use ServiceBus is out of question, because I don´t want to use Azure.
Instead of Redis, the guy recommends using RabbitMQ for horizontal scaling.
For the vertical scaling there is also socket.io-clusterhub, an IPC for node processes, but it seems to work only on Socket.io <= v0.9.0
Then there is this guy, who has implemented his own method to pass messages to other nodes via HTTP requests, which makes somehow sense. But why HTTP requests if you could also establish direct socket connections between servers, push the message to all servers simultaneously and overcome the delay of going from one server to another?
As a conclusion I thought maybe I could go with Redis on EACH server, just for the exchange of messages when clustering my application on multiple processes, together with RabbitMQ as a S2S communication solution.
But it seems a bit like an overkill to have one Redis per Server and another central RabbitMQ.
Is there any known shorter/better solution to scale Socket.io reliably in both directions?
EDIT:
I´ve tried using a single Redis Server for multiple Node.js Servers, where each of them uses Clustering via sticky-session over all cores. While the Clustering at its own works like a charm with redis, there seems to be a problem when using multiple servers. Messages won´t arrive at the other nodes.
I'd say Kafka is a good fit for the horizontal scaling. It is a fairly sophisticated way of distributing a huge amount of events across servers (which at the end is what you want). This is a good read about it: https://engineering.linkedin.com/kafka/running-kafka-scale
Regarding the vertical scale, instead of socket.io-clusterhub I would use something called PM2 (https://github.com/Unitech/pm2) which allows you to resize the scale of the apps in every computer dynamically as well as controlling the logs and reporting to keymetrics.io (if you are using it).
If you need any snippets ask me and I will edit the answer but in the PM2 github there are quite few.