AMQP NodeJS Connection - node.js

I have a Node application that will use RabbitMQ and I am using amqplib to access it. I understand that TCP/IP connections to RabbitMQ and expensive, channels are cheap so create one connection and then multiple channels.
What I am slightly confused about is how I rate that one connection that can be used across the application? Most tutorials seems to indicate that a connection is open for a purpose and then closed again only to be opened again when next required.
I would think that this would result in multiple connections if multiple users were attempting an action that required RabbitMQ access at the same time.

I suppose your users are only connected to your server which is different to each user is connected directly to rabbitmq. Then, server-side, you can keep only one connection to rabbitmq.
For that purpose, I would recommend to create a module to keep track of your connection across your application.
Note that AMQP has a heartbeat feature :
AMQP 0-9-1 offers a heartbeat feature to ensure that the application layer promptly finds out about disrupted connections (and also completely unresponsive peers). Heartbeats also defend against certain network equipment which may terminate "idle" TCP connections.
By default, amqplib's hearbeat is set to 0 meaning no heartbeat.

Related

What is the use of heartbeat in stomp protocol?

Currently I am using stomp protocol to send messages to activeMQ and to listen to messages. This is done in Nodejs using stompit library.
When the application is having high CPU or Memory usage, it stops sending heartbeat to broker. So the broker redelivers the message which is currently being processed, leading to repetitive processing of the same message
On disabling heartbeat, the application seems to work fine but I am unsure of the further issues disabling heartbeat might cause. Even when the broker is stopped while sending messages, behaviour seems to be same with or without heartbeat
I have read that it is an optional parameter but I am unable to find out it's exact use cases
Can anyone mention scenarios where no heart beat can cause issues to the application?
Regarding the purpose of heart-beating the STOMP 1.2 specification just says:
Heart-beating can optionally be used to test the healthiness of the underlying TCP connection and to make sure that the remote end is alive and kicking.
Heart-beats potentially flow both from the client to the server and from the server to the client so the "remote end" referenced in the spec here could be the client or the server.
For the server, heart-beating is useful to ensure that server-side resources are cleaned up in a timely manner to avoid excessive strain. Server-side resources are maintained for all client connections and it helps the broker to be able to detect quickly when those connections fail (i.e. heart-beats aren't received) so it can clean up those resources. If heart-beating is disabled then it's possible that a dead connection would not be detected and the server would have to maintain its resources for that dead connection in vain.
For a client, heart-beating is useful to avoid message loss when performing asynchronous sends. Messages are often sent asynchronously by clients (i.e. fire and forget). If there was no mechanism to detect connection loss the client could continue sending messages async on a dead connection. Those messages would be lost since they would never reach the broker. Heart-beating mitigates this situation.

How does Server keep track of all Client(s) connected in Real time data pushing scenario?

I kinda understand that Websocket is the protocol that is used for real-time data flowing back & forth.
My question can be very pre-mature but couldn't find much help on the web.
Say 1000 clients are connected to a server which sends out real-time stock prices. When there is an update on the server front, how will server know all the 1000 clients to which it needs to send an update?
If this is some sort of looping that happens on the server side where all connected clients details are cached & then update will be sent out to all of them, isn't is an overhead ?
This SOF answer made some sense but didn't clear my doubt.
How does Server keep track of all Client(s) connected in Real time data pushing scenario?
It doesn't... it only keeps track of the clients it's serving specifically.
This answer is not node.js specific.
Say 1000 clients are connected to a server which sends out real-time stock prices. When there is an update on the server front, how will server know all the 1000 clients to which it needs to send an update?
To actually understand this a little better, we should consider larger numbers. i.e., let's assume 1 million clients connected to a service.
Obviously, a sane design will require redundancy, so no single service will hold all 1 million connections (and if a single server instance fails, clients can re-connect to a different server instance).
In this case, there's no single server that is aware of all clients.
It makes more sense for each server to manage it's own internal subscription / client list. Each server will also act as a pub/sub client for a centralized pub/sub service (such as a Redis cluster or whatever).
Assuming 1000 server instances, each serving 1000 clients, we would have find that the pub/sub service is aware only of 1,000 "clients" (server instances). Each server is unaware of the other clients, it's only aware of the 1,000 clients it's managing.
If this is some sort of looping that happens on the server side where all connected clients details are cached & then update will be sent out to all of them, isn't is an overhead?
The algorithm itself is implementation specific, but in general, each server will incur some overhead in order to manage the pub/sub layer.
However, since each server only manages a small subset of the total client count, the overhead is distributed across a number of systems.
Channel Oriented vs. Connection Oriented Design
I should probably note that the pub/sub design isn't connection oriented.
The server isn't (or shouldn't be) looping over all the connections asking "are you subscribed to this channel"?.
Rather, pub/sub design assumes a "channel" oriented design, where it locates the channel object(s) and loops over a client list.
On one hand, this approach might (or might not) consume more memory. Since each "channel" should contain a list of clients listening to that channel, a single client object might belong to more than a single list.
On the other hand, the loop has less code branches and experiences less overhead than a connection oriented design. Also, this approach allows for pub/sub clients that aren't connection bound (such as internal hooks / callbacks).
Say 1000 clients are connected to a server which sends out real-time stock prices. When there is an update on the server front, how will server know all the 1000 clients to which it needs to send an update?
Socket.io already keeps track by itself and its pretty easy to emit to all connected clients.
Socket.io - Emit Cheatsheet
If you are worried about what would happen when your user-base grows, you can scale your service to multiple nodes.
If you actually end up scaling and have more than one server node, then you can use
socketio-redis.
Adapter to enable broadcasting of events to multiple separate socket.io server nodes.

Multiple websockets onto multiple servers: how do they communicate?

I have a node server accepting websocket connections from the clients. Each client can broadcast a message to all of the other clients.
UPDATE: I am using https://github.com/websockets/ws as my library of choice.
At the moment, the server has an array with all of the connections. Each connection has a tabId. When one of the client emits a message, I go through all of the connections and check: if the connection's tabId doesn't match, I send the message to the client.
For loading issues, I am facing the problem of having to have more than one server. So, there will be say two servers, each one with a number of clients.
How do I make sure that a message gets broadcast to all of the websocket clients, and not only the ones connected to the same server?
One possible solution I thought is to have the connections stored on a database, where each record has the tabId and the serverId. However, even a simple broadcast gets tricky as messages to "local" sockets are easy to broadcast (the socket is local and available) whereas messages to "remote" sockets are tricky, and would imply intra-server communication.
Is there a good pattern to solve this? Surely, this is something that people face every day.
You could use a messagequeue like RabbitMQ.
When a client logs in to your server, create a consumer which listens to a queue which will receive messages directed to that particular client. And when the clients are sending messages, just use a publisher to publish them to the recipients queue.
This way it doesn't matter and you don't need to know on which nodes the clients are on, or if they jump from a node to another.

Real time comunication between servers and clients

I have a socket game server that runs everything on one single process; the problem is when i want to scale out my app.
Since it is a card game and when there is an event on a table, i can easily reach all the players that are in the same room because i have direct access to their socket connection.
if i want another server (or many depending on the load) it is another complete different process and i need to be able to have for instance 1 room, where players from server 1 can play against players from server 2, and in case server 1 fails, the connections can be taken from server 2 and keep them playing without interruptions.
What would be the architecture for this?
Some hosting providers support both websockets and horizontal scaling. This will allow your users to establish a websocket connection with a node. However, you may need an event from that user to broadcast to other users connected to other notes.
You may want to consider something like RabbitMQ. By using a fanout or topic exchange you can broadcast the event to a set of listeners. The listeners will be the various nodes in your cluster that are maintaining the websocket connections.

With a Node.js cluster, how do I share connections?

I have an Azure hosted application (iisnode) that accepts direct connections from multiple client services. This application streams data between the various connections. If running on a system with multiple instances of node.js, the actual TCP connections will be connecting to different instances.
Is there a way to somehow "move" or "share" the in-memory connection from one instance to another?
Sure, I could build some inter-instance communication to route data, but I don't think the application will scale since it's entire purpose is to move data around quickly. For example, I would have 4 instances, 100 connections to each, and I would spend as many resources moving the data between instances as I would spend moving the data between the client connections.
When you configure iisnode to create more than one node.exe process (using the nodeProcessCountPerApplication setting), it will dispatch incoming HTTP requests between them using a round robin logic; the application has no control over that behavior. Given your scenario there is no way to deterministically ensure that the requests ("connections") from two distinct clients will be colocated in the same node.exe process.
There is no mechanism to "move" an existing TCP connection or HTTP request between node.exe processes.
In general a better way to address such a notification scenario may be to use a subscription-based messaging infrastructure as your backend. ServiceBus in Azure provides such mechanisms. In this design, each instance of node.exe would subscribe to a particular topic when it receives a connection from the client, and be notified by ServiceBus when a matching notification arrives, possibly via a different instance of node.exe.

Resources