Spring Web Socket not broadcasting message to all application servers - grails

I am trying to setup load balanced environment having 2 application server instances. I am unable to make spring web socket relay messages to all instances. Let's take a example to describe my problem better:
Server 1 : Responsible for job executions and 35% user load.
Server 2 : 100% user load.
Both are connected to same database schema so job request can come for any server instance but will get executed on Server 1.
Now, I have used spring web socket plugin for my GRAILS application and I push messages to browser using
brokerMessagingTemplate.convertAndSend(user.notificationChannel, ((notification.toMap(user) as JSON)).toString())
It was working fine on single server setup. But on multi-server setup,
notifications are only received on Server 1 as that is the one calling the code block, if reverse the scenario, then vice-versa result is observed.
How can I push same notification to all server instances, so that user always gets the notification no matter what server instance he is on?
I initially thought of utilising a common queue like RabitMQ but that will add to system requirements and will get disapproved by client.
NOTE: Third party service solutions won't work in my case as applications are on intranet and don't have internet access.

websockets by default point to a hostname/ip address - whilst you could setup a dns record / hostname that points to multiple different ip's / servers. This itself would break communication flow of the websockets if it sent handshake to one and the message to another.
The most simplest approach would be to think of some db table that is shared across both and as each instance comes up/alive it records its local ip / socket port to a db table - each instance can then read this table and work out at any point which are the hosts to transmit a socket message to - (this table would need to managed somehow - upon a brand new bootup ) it would be empty and would popuplate as instances came up - something again to manage when a host is taken down shutdown.
Each instance would then be running an ws internal client. When a message is sent the ws client would be triggered attempting to find all alive websocket servers "from the db" to each using the ws client it would attempt to connect and send the message on. Each would then get the message and either broadcast to all connected users or if it is from user x meant for user x then like per chat plugin it would relay it only to user x if found on server y and so on.
this then keeps it all inline with 1 technology controlling the entire process websocket server that has its own client which relay to the end multiple instance ws socket server

Related

Pre-authentication steps in ejabberd

I am working on a project like whatsapp and using ejabberd as a backend server with Android/IOS clients. I want to do some whatsapp like step-
1. Client sends mobile number to server.
2. server sends OTP in return to the client and starts a timer say 2 minutes.
3. If client sends correct OTP, received from the server, to the server within the time specified. Client will be registerd.
I need help in which ejabberd module should I write the code of above steps. I know, to modify Ejabberd I can use Hooks and IQ handlers, but they can be used once the user is already registered. Right?
Should I use other language server, just for the above steps? Please help.
You should write new ejabberd module which starts a new SSL server on a specific port. Do your authentication on that.
If you are familiar with ejabberd's core, you can add your own module in listen part of config and write new module as backend of your server (same as ejabberd itself which wrote ejabberd_c2s, ejabberd_service, etc).
I just read its code and i recommend to read the code too.
For example in ejabberd version 17.01 here reads config and runs a tcp server for every section of listen key. every section has three parts Port, Module and Opts. For xmpp clients of ejabberd these are 5222, ejabberd_c2s and Opts is other values. in here for every accepted connection it calls ejabberd_socket:start(Module, gen_tcp, Sock, Opts). In ejabberd_socket:start/4 here starts a process say A for receiving from socket and parsing XML and send them to another process say B and here starts a process (B) from ejabberd_c2s. Process B receives XMLs from Process A and does all actions off XMPP clients in ejabberd.
I think you should create a restful service to do this.
Please consider following steps:
Client sends mobile number to restful service.
The restful service create a OTP and save it in Redis with expired is set.
The client sends OTP to restful service. If the OTP is correct, service sends a jwt Token to client and save it in Redis with expired is set.
The client sends jwt token to eJabberd server and the server authenticates with ejabberd_auth_jwt module.
This may meet your requirement.

A web app that connects to local server; is that safe?

I am writing a rails app that comes with a local program for the user to run. That program creates a nodeserver which connects to the user's browser through websockets. Upon certain actions by the user in the browser, a signal will be sent through the socket to the local node server which will execute a pre-defined command on the user's local machine. The command differs depending on the user's specific action in the browser, but there is no way for the user to send custom data to the local node server(ie different actions send pre-defined information to the local server). I was wondering if there are security implications to doing this, and what some possible exploits might be if so.
I had troubles working on a Chrome Extension communicating with a local environment with this:
Maybe you can have problems with HTTP access control (CORS) and gem CORS could fix if that happens http://rubygems.org/gems/cors
Another possible problem may be "406 not acceptable" because of CORS.

ruby on rails chat application over port 80 which is hosting site agnostic(no flash and websockets)

Wanted to build a chat like application(i.e bidirectional message passing to multiple connected clients). Looked at the Faye gem but it opens a new port apart from port 80.
The big problem is that if the client is behind firewall all access to other ports except 80 are restricted and not all the hosting sites provide the support.
The ActionController::Live component does not have any mechanism to register the clients so that the message can not be passed to the registered clients on a specific event occurance.
Looking for a solution where the alive clients are stored in a collection(array or somthing like that) and when any of the alive client sends a message then the collection can be iterated and the messages can be written on it. All of these must happen only through port 80.
Good question - having implemented something similar, let me explain how it works:
Connections
A "live" web application is not really "live" at all - it's just got a persistent request; meaning it still works exactly the same as a "normal" Rails app, except clients don't close the connection (hence why you're interested in opening another port)
The way you handle the request is where the magic happens. This is as much to do with the client-side, as it is with Rails (server-side)
Clients
When you connect to a "chat" application, your browser is opening a live connection with the server. This will typically be done with either server sent events (Ajax long polling), or web sockets
The way this works is to open the connection using the normal Rails ActionDispatch middleware, and then allow you to connect
If you've played with ActionController::Live functionality, you'll find that it's not a typical controller-action. It's actually a separate technology (like resque or Redis) which you call from another controller action. This gives room to do cool things with
Server
The way you'd handle something like this is to separate the "live" functionality and the "normal" Rails app. It's one of the current down-falls of Rails - in that it's probably better to implement something like nodeJS with socket.io to handle the live data (with an endpoint like chat.yourapp.com), whilst using Rails to handle authentication & authorization
From a server perspective, its job is to handle incoming & outgoing requests -- not to handle persistent connections. So I guess you may want to look at ways you could "outsource" the websocket connectivity. Admittedly, my experience is slightly thin in this area, so you may do well searching the net
Solutions
We've had a lot of success using a third-party system called Pusher
This is a web socket system which allows you to open a persistent connection as a client, and integrates with Rails in a similar way to Redis (you can push to it)
This means you can host the "chat" application with Rails (http://yourapp.com/chat), send the messages to your Rails app (http://yourapp.com/chat/send), and handle the incoming chats from pusher (or similar)
Maybe you want to use my open source comet web server (https://github.com/TorstenRobitzki/Sioux). There is a ruby web chat example. I use this to implement an interactive role playing map with rails (http://dungeonpilot.com).

Websockets - passing-off open connection to another server?

Situation: Two web servers, and a browser client. The client has an open websockets connection with Server A. Server A decides that this client should really be serviced by Server B.
I would like to know if there is any established technique for performing this hand-over?
It would be great if this could happen as invisibly as possible for my client side code - but I haven't come across any feature which would allow this.
Best I have come up with so far is Server A sending a 'you should really deal with Server X' message, client closing the WS session and then sending some http request which will get routed to the correct server, and upgraded to WS. I can see the presense of load balancers making this complicatied though.
Any thoughts?
From a programming point of view, the socket connection is treated as an open file handle, and that's what you are trying to pass along. For that, I would check out the question "Portable way to pass file descriptor between different processes" for a handful of methods.
But if you are not writing your own web server, and are looking for an off-the-shelf method for Apache, etc, this probably won't help you much.

User Disconnection Detection (i.e. "Online Status") Daemon

Summary: is there a daemon that will do postbacks when a user connects/disconnects via TCP, or is it a good idea to write one?
Details:
There are a number of questions based around this already; but I believe that this is a different "twist" on it. We're writing a Ruby on Rails web application, and we would like to be able to tell if a user is "online" or "offline", where the following definitions apply:
"online" - the user's browser is open and maintaining a TCP connection to one of our servers.
"offline" - the user's browser is no longer connected to one of our servers.
What we're thinking is a convenient way of doing this is to run a completely separate "online state" server that each of our users will connect to (exactly once):
when a connection is made to the "online state" server, it will postback to our actual RoR site and let it know "this user just logged on".
when a connection is lost from the "online state" server, it will postback to our actual RoR site and let it know "this user just logged off".
This methodology seems reasonable and keeps things quite modularized (the online state server, for instance, will be quite simple, which is nice). We're able to write this online state server, but have the following questions:
Any specific problems with the above architecture that we haven't taken into account?
Is there a daemon or application out there that does this already? Why reinvent the wheel, if it has already been written?
Is there a push server out there that offers this functionality (i.e. it maintains connections to the users, but will postback or send notifications upstream to the web servers when a user connects or disconnects?)
Is this something you envisage users would install on their systems?
If you are looking for a browser based system, WebSockets are probably your only option using something like Socket.IO http://socket.io/.
The node.js socket server provided as part of this project can be found on github: http://github.com/LearnBoost/Socket.IO-node
Node.js is a great platform designed for exactly this problem domain and there are a number of WebSocket servers for node.
Unless your app is entirely ajax based and uses a single parent page, you would need to create a persistent parent frame containing the socket that wraps your application, as each time the user clicks a link the page unloads and reloads, resulting in disconnection and re-connection from the state server.

Resources