Connectivity between NodeJS applications behind load balancer - node.js

I'm currently working on nodejs application and I got small issue.
My NodeJS application consists of 2 parts:
Internal API from other applications. Let's call this part API.
User faced web server (Express + Socket.io). Let's call this Web.
We're receiving a lot of calls to API from our other internal applications. Some of this calls would generate notifications to web users (let's imaging it's online-chat).
So if we have message for client #1000 and he's online (connected to Web application through Socket.io) we would emit message throught Socket.io to this client. Everything works fine.
But there is an issue.
We're going to introduce load balancer between our NodeJS application (it's one application, so both parts - API and Web would be behind the load balancer). Now let's imagine that we have load balancer and 2 servers with this application: server1 and server2.
Thus some of API calls are sent to server1 and some of them are sent to server2. So let's imagine we got API call to server1 and this call should send a message to client #1000. But this client has open connection to server2.
The question is: is there any best practices or common solutions - how these two servers should communicate? One of possible solutions could be open socket connection between all servers with nodejs application and if we need to send a message to client - just broadcast it so every server could check if client is connected at this moment and send the message to correct client.

Related

Push Notifications RESTful WebApp Angular2 / NodeJS

I'm working on a Restful Web Application. I divide frontend and backend, using Angular2 for the front, and NodeJS for the back.
I would like to use Notifications and push them to specific users.
Sample : If my user decide to subscribe, he could get a Desktop notification when I decide to send one or if my NodeJS serveur want to send a message to a user group.
I have seen a lot of differents modules for the frontend and backend, but I'm a little bit lost.
Architecturally, how should I add this service in my application?
Should I use specific node modules?
You talk about desktop notifications. I guess you want the user to receive its notifications also when the browser or app is closed. In that case you need a Service Worker. A Service Worker is a script that your browser runs in the background, to which the message is being pushed when the browser or app is closed. For a nice introduction to Service Workers, read this. Angular has a Service Workers implemented in production version since 5.0.0. Klik here to read more about it.
At the backend you need a special Node module to send the notification. For instance node-pushserver, but there are many others. This special node module connects to a messaging service whom actual send the message. You can use for instance Google's cross-platform messaging solution Firebase Cloud Messaging (FCM) (the successor of Google Cloud Messaging (GCM)). It can send to Web, iOS and Android.
At the client side you need to register the Service Worker for push notification. Then you will get an endpoint that needs to be stored at the node server side. You send a push request with this endpoint to the messaging service every time.
You can also make use of a paid push notification provider to do the job. Click here for a list of them.
Setting up a WebSocket connection (like socket.io) won't work since it can't stay connected with the Service Worker.
You can use WebSockets for pushing data from the Node.js server. Add the ws package to your server's package.json. Take a look at the BidServer.ts here: https://github.com/Farata/angular2typescript/tree/master/chapter8/http_websocket_samples/server/bids
The Angular client is here: https://github.com/Farata/angular2typescript/tree/master/chapter8/http_websocket_samples/client/app/bids

Azure relay hybrid connection - multiple servers (one premise) one client

I want to build a service using Azure relay hybrid connection. The service will be downloaded by the customers and installed on their premise. The service itself is a server basically that will allow a client to connect to and get data from a database. I am following this scenario here : Azure Relay Hybrid Connection and works fine when you have one client and one server. My scenario is something like this (one client and many servers):
How can I build a dynamic server in such way that one client can connect to a specific server and get the data from the database?
I was thinking about having some config file that is generated when the customer downloads the server and the server will read the settings from the file, but still how do I connect to a specific server? Azure service bus topics and subscriptions work in similar way. Can this be achieved using the relay hybrid connections?

Node.js Server Sent Events with Load Balancer

I am working on a node.js based Web application that needs to be able to push data down to the browser. The Web app will be sitting behind a load balancer.
Assuming the Web app has a POST REST API as:
/update_client
and assuming there is a third-party application calls this API to push some data to the Web app, and then the Web app pushes the data down to the browser.
Now assuming I have two servers behind the load balancer, with the Web app running. A browser client connects to server 1 to listen on the event. Then the other applications hits the /update_client API at the server 2. Now since the two activities happen on two different servers, how can server 2 notify server 1 to send the data to the connected clients?
And what if I am using auto scaling, with dynamic number of servers behind the load balancer?
You need to have some kind of shared resource behind the servers so they all know about updates. I show how to use Redis Pub / Sub for this in a blog post I wrote recently.
Server Sent Events with Node JS

RabbitMQ security in mobile app

I am using Rabbit MQ broker in one of mobile apps that we are developing, I am bit puzzled about security aspects. we are using cloud hosted rabbitmq and hosting platform has given us user name and password (which have been changed since) and we are using SSLconnection so not so much worried about MIM or eavesdropping.
my concern is anybody who knows host and port can make connection to rabbitmq, since we have mobile app we are storing rabbitmq user name and password on device (although encrypted) so I guess that anybody who gets physical access to device and somehow decrypts username password can login to rabbitmq, and once you are logged in you can pretty much do anything on rabbitmq like deleting queues etc..
How are MQ like Rabbitmq used in mobile environment. Is there a better / more secure way of using rabbitmq.
In my experience, it is best to not have your mobile app connect to rabbitmq directly. Use a web server in between the app and RabbitMQ. Have your mobile app connect to your web server via HTTP based API calls. The web server will connect to RabbitMQ, and you won't have to worry about the mobile app having the connection information in it.
There are several advantages of this, on top of the security problem:
better management of RabbitMQ connections
easier to scale number of mobile users
ability to add more logic and processing to the back-end, as needed, without changing the mobile app
creating a connection to RabbitMQ is an expensive operation. It requires a TCP/IP connection. once that connection is open it stays open until you close it. if you open a connection from your mobile app and leave it open, you are reducing the number of available connections to RabbitMQ. if you open and close the connection quickly, you are inducing a lot of extra cost in creating and closing the connections constantly.
with a web server in the middle, you can open a single connection and have it manage multiple mobile devices. the web server will handle the http requests and use the one connection to rabbitmq to push messages to it.
since an HTTP web request is a short-lived connection, you'll be able to handle more users in a short period of time, than you would with direct rabbitmq connections.
this ultimately leads to better scalability as you can add another web server to handle thousands more mobile app instances, while only adding 1 new RabbitMQ connection.
this also lets you add middle-tier logic inside of the web server. you can add additional layers of processing as needed, without changing the mobile app. change the web server code and redeploy as needed.
if you must do this without a server in the middle, you likely won't be able to get around the security issue that you're having. the mobile device will contain the necessary information to make the connection.

SignalR on multiple Windows Azure instances (no backplane)

I'm currently working on a Windows Azure application using WebAPI and SignalR for communication. Both services are hosted via OWIN on a Worker role with multiple instances.
Current solution
Currently we start one Owin host with WebAPI on port 443 on every machine and one SignalR Owin host on the instance input endpoint port (e.g. 10106-1010x) on every machine.
Everything works fine, but some of our customer are sitting behind a firewall where all ports except 80/443 are blocked -> so no websocket communication there (WebAPI works fine).
New solution
We are starting one Owin host with WebAPI and SignalR on every instance. So both HTTP and WebSocket traffic will be routed through the loadbalancer over port 443 -> no more instance input endpoints (and no more firewall problems).
The problem
The problem now is that sometimes the WebSocket connection can be established and sometimes not (browser independent). If the connection can't be established the following error appears in the console:
Error during WebSocket handshake: Unexpected response code: 400
No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.
I've already added the role instance id to the websocket response messages from the server, but couldn't find any (ir)regularities (e.g. a single instance doesn't respond, ...). All SignalR servers seem to be up and running, but sometimes the connection can't be established.
You can test it yourself by going to the following link. If you don't get an error dialog ("Connection to server lost") it is working, otherwise try to refresh the page several times.
-
I'm not looking for a scaleout feature for SignalR (as described here or here). The client just connects to one (random) server (worker role instance) and communicates with the server until a close message is sent. If he connects again he can be routed to any other server. Also there is no communication between the servers.
Update/Solution
halter73 was right, each instance generates its own anti-CSRF token. To avoid this I implemented my own IDataProtector/IDataProtectionProvider, similar to these to SO questions (see here and here).
If you can look at content of the 400 response (this may be difficult since it is an SSL encrypted response to a WebSocket request), you will probably see a message similar to "The ConnectionId is in the incorrect format."
SignalR uses the server's machine key to create an anti-CSRF token, but this requires that all the servers in your farm share a machine key for the token to be properly decrypted in when SignalR requests hop servers. The /negotiate is the request that retrieves the anti-CSRF token. When the SignalR client then uses the anti-CSRF token to make a /connect request, it sometimes fails when the /connect request is processed by a different server which didn't create the token and therefore is unable to decrypt it.
Here is an issue that filed on GitHub by someone who experienced a similar issue: https://github.com/SignalR/SignalR/issues/2292.

Resources