How can I Use RabbitMQ between two application while I can't change one of them? - rabbitmq

I have an existing system consisting of two nodes, a client/server model.
I want to exchange messages between them using RabbitMQ. I.e. The client would send all its requests to RabbitMQ and the server would listen to the queue indefinitely, consume any messages that arrives and then act upon it.
I can change the server as needed, but my problem is, I cannot change the client's behavior. How can I send back the response to the client?
The client node understands HTTP request/response, what shall I do after configure the other application server to RabbitMQ instead of my app directly.

You can use RPC model or some internal convention, like storing result in database (or cache) with known id and polling your storage for that result in a cycle

You will have to use a proxy server in between that will seem to node 1 (the client you cannot change) as the actual server while it just inject requests into the queuing server. You will also have to use 2 queues.
For clarity, let's enumerate the system players:
The client
The proxy server, a server that offers the same API offered by the actual (but it doesn't do any work)
The actual server, the server that does the actual work
The input queue, the queue where clients requests go into (proxy server does that)
The output queue, the queue where server responses go into (actual server does that)
A possible working scenario:
A client sends a request to the proxy server
The proxy server puts the request in input queue
The actual server (listening to the input queue) will fetch the request
The actual server process the message
The actual server sends the response to the output queue
The proxy server (listening to the output queue) will fetch the response
The proxy server returns the response to the client
This might work, but few problems could happen, e.g. because the proxy server doesn't know when the actual server will response, and, it cannot be sure of the order of responses in the output queue, it may have to re-inject the messages it finds not relevant to the output queue until it finds the correct message.
Or, the proxy server might need to feed the response to the client later via an HTTP request to the client. That is, rather than a response to the client's request, the client will expect no response for the request it sent knowing that it will be get the answer later via a request from the proxy server.
I'm not aware of the situation at your end, but this might work!

Related

CometD Failover Ability - VM Switch During Restart

I have a chat implementation working with CometD.
On front end I have a Client that has a clientId=123 and is talking to VirtualMachine-1
The longpolling connection between the VirtualMachine-1 and the Client is done through the clientId. When the connection is established during the handshake, VirtualMachine-1 registers the 123 clientId as it's own and accepts its data.
For some reason, if VM-1 is restarted or FAILS. The longpolling connection between Client and VM-1 is disconnected (since the VirtualMachine-1 is dead, the heartbeats would fail, thus it would become disconnected).
In which case, CometD loadBalancer will re-route the Client communication to a new VirtualMachine-2. However, since VirtualMachine-2 has different clientId it is not able to understand the "123" coming from the Client.
My question is - what is the cometD behavior in this case? How does it re-route the traffic from VM-1 to a new VM-2 to successfully go through handshaking process?
When a CometD client is redirected to the second server by the load balancer, the second server does not know about this client.
The client will send a /meta/connect message with clientId=123, and the second server will reply with a 402::unknown_session and advice: {reconnect: "handshake"}.
When receiving the advice to re-handshake, the client will send a /meta/handshake message and will get a new clientId=456 from the second server.
Upon handshake, a well written CometD application will subscribe (even for dynamic subscriptions) to all needed channels, and eventually be restored to function as before, almost transparently.
Messages published to the client during the switch from one server to the other are completely lost: CometD does not implement any persistent feature.
However, persisting messages until the client acknowledged them is possible: CometD offers a number of listeners that are invoked by the CometD implementation, and through these listeners an application can persist messages (or other information) into their own choice of persistent (and possibly distributed) store: Redis, RDBMS, etc.
CometD handles reconnection transparently for you - it just takes a few messages between client and the new server.
You also want to read about CometD's in-memory clustering features.

how the server send message SSE worked in multiple server instance environments

I have a question on how to make SSE worked in multiple server environments.
In UI, there are two steps:
1. source = new EventSource('http://localhost:3000/stream');
source.addEventListener('open', function(e) {
$("#state").text("Connected")
}, false);
user in UI can post to api to update data
after user post to api, server is sending event to UI to udpate UI
In one server environement, this worked perfect fine, no problem at all.
But in multi server instance environments, this won't be working. For example, I have two server instance, and UI subscribed to server 1, then server 1 is remembering the connection, but data update is from server 2, when data is changed, there is no connection for SSE in server 2. Then in this senario, how can server 2 send SSE to UI?
In order to make SSE working in multiple server environments, do we need to adopt any saving solution to save the connection information so that any server instance can send SSE accurately to UI?
Let me clarify this more:
yes, both service 1 and service 2 are behind load balancer, they do not have to have same URL. UI is pure frontend end application, can even be mobile app. So, if UI is sending a eventSource request to LB of server1, then only this instance can use this connection to send event back to UI, right? But if we have multiple instance of server 1, that means any server 1 instance other than current one can NOT send event back to UI.
I believe this is the limitation of SSE unless the connection can be shared among all the instances. But how.
Thanks
If you have two servers, with different URLs, make one SSE connection (from each client) to each server.
Be aware of CORS restrictions, i.e. the same origin policy. (It works identically to xhr2 CORS, so fairly easy to google; my book also covers it in detail, chapter 9.)
If you have two servers behind a load balancer, which is presenting a single URL to the clients, then you just have to make sure the load balancer is configured correctly. I.e. to always pass through that socket to the correct server. If a back-end server dies, and needs replacing, the load balancer should close the SSE socket; the client will then auto-reconnect, and get a new back-end server.
The multiple servers behind a load balancer, should either be having their own data push socket connections to a master data source, or should all be polling the master data source.

Redis how to match roundtrip request response

I have a http server application that receives requests from HTTP clients and puts them to a Redis List for processing. Another process listening on this list picks up the requests and processes them, and finally puts the response into another Redis Queue to be consumed by the HTTP server.
The sequence is like this:
(1) Http Client ==> Web app
(2) Web App ==> Redis Request Queue (List data structure)
(3) Processor ==> consumes requests using multiple threads and processes them
(4) Processor ==> puts to a Redis Response Queue (List data structure)
(5) Web App ==> has to pick the response from the response que and deliver to HTTP clients
Given the above scenario, if multiple threads on the HTTP server are queueing the msgs to Redis, is there any established pattern to ensure responses are correctly picked up and sent back to HTTP clients using the right session?
I am planning to use Redis (or may be RabbitMQ or ZeroMQ) for the producer/consumer, because I want to scale horizontally and configure many consumers spread across several nodes.
Thanks for pointing me a reasonable approach on this.

TCP server test

i have a TCP server (listener) software written in C#. Many devices (approximately 5000) will connect to server asynchronously and send/receive messages to/from server. Now, i have 2 questions.
I have to send reply messages to every received message. Which way should i use? Asynchronous (asap when message received) or synchronous (sending replies using a reply task).
How can i strain test my server? I can communicate with 1-2 computers successfully but i don't know that my software works fine for 5000 devices.
Judging from what your saying, your server or listener is expected to be available to respond to multiple requests at any given time. The key is how has it been implemented ? Does the server support multi client response, in other words can it fulfill requests of multiple clients at the same time ? May be using multiple threads etc ! Or does it use a queue to keep track of all requests and then serve them in a orderly fashion, or does it use some other method to serve requests !

Getting result of a long running task with RabbitMQ

I have a scenario where a client sends an http request to download a file. The file needs to be dynamically generated and typically takes 5-15 seconds. Therefore I am looking into a solution that splits this operation in 3 http requests.
First request triggers the generation of the file.
The client polls the server every 5 seconds to check if file is ready to download
When the response to the poll request is positive, the client starts downloading the file
To implement this I am looking into Message Queue solutions like RabbitMQ. They seem to provide a reliable framework to run long running tasks asynchronously. However after reading the tutorials on RabbitMQ, I am not sure how will I receive the result of the operation.
Here is what I've in mind:
A front end server receives requests from clients and it posts messages to RabbitMQ as required. This front end server will have 3 endpoints
/generate
/poll
/download
When client invokes /generate with a GET parameter say request_uid=AAA, the front end server will post a message to RabbitMQ with the request_uid in the payload. Any free worker will subsequently receive this message and start generating the file corresponding to AAA.
Client will keep polling /poll with request_uid=AAA to check if task was complete.
When task is complete client will call /download with request_uid=AAA expecting to download the file.
The question is how will the /poll and /download handlers of the front end server will come to know about the status of the file generation job? How can RabbitMQ communicate the result of the task back to the producer. Or do I have to implement such mechanism outside RabbitMQ? (Consumer putting its results in a file /var/completed/AAA)
The easiest way to get started with AMQP, is to use a topic exchange, and to create queues which carry control messages. For instance you could have a file.ready queue and send messages with the file pathname when it is ready to pickup, and a file.error queue to report when you were unable to create a file for some reason. Then the client could use a file.generate queue to send the GET information to the server.
You hit the nail on the head with your last line:
(Consumer putting its results in a
file /var/completed/AAA)
Your server has to coordinate multiple jobs and the results of their work. Therefore you will need some form of "master repository" which contains an authoritative record of what has been finished already. Copying completed files into a special directory is a reasonable and simple way of doing exactly that.
It doesn't necessarily need RabbitMQ or any messaging solution, either. Your server can farm out jobs to those workers any way it wishes: by spawning processes, using a thread pool, or indeed by producing AMQP events which end up in a broker and get sucked down by "worker" queue consumers. It's up to your application and what is most appropriate for it.