I am implementing websockets for collaborative editing. For that I am using Spring 5 websockets.
The simplest example would be, two web clients are connected via websockets to my server. User 1 does some action which creates an event and sends this event info to my server. Now this event has to be sent to User 2 so that they can do appropriate UI changes.
I have two questions here:
Since there will be multiple instances running of this server, User 1 might connect to Server 1 and User 2 might connect to server 2. In this case how would the changes done by User 1 go to User 2 ?
Also, I was following this tutorial. This tutorial is implementing websockets without any message broker some tutorials are additionally using a message broker (amqp mostly). What is the point of a message broker in this case ? Is it only used because there might be too many messages and the server would be processing them one by one ?
Just wanted to add: We cannot get away with a peer to peer connection on the client side as the server needs to store the data for future.
By default spring 5 uses in memory simple stomp broker for all connections
If you want to scale horizontally you need a message broker like RabbitMQ etc.
Lets imagine the situation user1 and user2 is connected to server1 and user3 is connected to server2 . When user1 sends a message to user3 it would not be aware of user3 because server1 does not know about user3.
If we have a broker this issue will be solved.
So scalability is needed to handle the load and in production you always will have more than 1 instance for high availability and fault tolerance.
Related
I want to run a Java based message broker that will route messages to web clients. Web client connections are handled on our server using our custom Java websocket code, which authenticates users against the user database.
I think my server side websocket handler code would connect to ActiveMQ and perform subscription management via AQMP.
I have a specific requirement however:
route messages for a topic specifically to one or more web clients
Note that I don't need to retain messages if a client is not connected. Messages are being used to inform the web client applications of actions they need to take.
I'm considering ActiveMQ but I was hoping people with experience of the product could clarify if it supports this requirement?
If ActiveMQ isn't the best option, could you recommend something else?
Thanks
Yes, ActiveMQ is a great choice for this.
As far as specific approach goes, it depends on your data model and message flow.
You have several options, including:
Produce and consume to a topic-per-client
a. Messages for Client ABC go to topic://CLIENTS.ABC, for Client XYZ go to topic://CLIENTS.XYZ, and the subscribers connect accordingly.
Produce a message with a header and use a consumer-side selector (aka 'filters' in AMQP) to filter messages on a per-client basis. (abc client subscribes to-- ClientId = ABC, xyz client subscribe to-- ClientId = XYZ)
When using WebSockets, you might also look to STOMP which is text-based protocol. (Just depends on your programming language and available libraries that you had in mind)
After googling how message is sent/received in chat messenger like whatsapp, i came across they use queues based messaging system. I am just trying
to figure out what can be high level design of this feature
HLD per mine understanding :-
Say Friend 1 and Friend 2 are online . Friend 1 has established HTTP web connection to web server 1 and Friend 2 has established HTTP web connection to web server 2. Friend 1 send the message to Friend 2.
Now as soon as message comes to web server 1, i need to convey the message to web server 2 so that message can be pushed back to friend 2 through already established web connection.
I believe distributed custom java queues can be used here to propagate the message from one server to another. As soon as message comes to one server , it will push it to distributed queue(distribute queue because of load balancing and high availability) with message content, fromUserId, toUserId. There will be listener on queue which will see destination userId of just poppedIn message and find on which webserver destination userId is active . If user is active pop out the message and push it to client otherwise store it in db so that it can be pulled
once once gets online. To see which user is active on which server, there we can maintain the treemap with userId as key and value as serverName for efficient look up
Probably actual design must be more complex/scalable than above brief . Would like to know if this is the right direction for scalable chat messenger?
Also i believe we need to have multiple distributed queues instead of one for such a scalable application. But if we have multiple distributed queues how system will ensure the FIFO message delivery across distributed queues ?
Would like to know if this is the right direction for scalable chat
messenger?
Designing this application using message queues has the following benefits:
Decoupling of client-server and reduce of failure blast: Queues can gracefully handle traffic peaks, by just having a temporarily increased queue size, which will be back to normal as long as traffic normal again (or any transient failures have been fixed)
In a messaging application, clients (mobiles) can be offline for long periods. As a result, a synchronous design would not work, since the clients might not be accessible for message delivery. However, with an asynchronous design as with message queues, the responsibility of message delivery is on the client side. As a result, the client can poll for new messages as soon as it gets online.
So, yes this design could be quite scalable in terms of performance and usability. The only thing to have in mind is that this design would require a separate queue for each user, so the number of queues would scale linearly with the number of the application's users (which could be a significant financial & scalability issue).
But if we have multiple distributed queues how system will ensure the
FIFO message delivery across distributed queues ?
Many queues, either open-source (rabbitMQ, activeMQ) or commercial (AWS SQS), support FIFO ordering. However, the FIFO guarantee inside the queue is not enough, since the messages sent by a single client could be delivered to the queue in different order due to asynchronicity issues in the network (unless you are using a single, not-distributed queue and TCP which guarantees ordered delivery).
However, you could implement FIFO ordering on the client side. Following this approach, the messages would include a timestamp, which would be used by each client to sort the messages when receiving them. The only side-effect of that is that a client could see a message, without having seen all the previous messages first. However, when previous messages arive, they will be shown in the correct order in the client's UI, so eventually the user would see all the messages and in the correct order.
Would like to know if this is the right direction for scalable chat messenger?
I would probably prefer a slightly different approach. Your ideas are correct, but I would like to add up a bit more to the same. I happened to create such a chat messenger a few years ago, and it was supposed to be quite similar to watsapp. I am sure that when you googled, you would have come across XMPP Extensible messaging and presence protocol. we were using openfire as the server that maintains connections . The concept that you explained where
Say Friend 1 and Friend 2 are online . Friend 1 has established HTTP web connection to web server 1 and Friend 2 has established HTTP web connection to web server 2. Friend 1 send the message to Friend 2.
is called federation, and openfire can be run in a federated mode. After reading through your comments, i came across the one queue per user point. I am sure that you already know that this approach is not scalable as its very resource intensive. A good approach would be use an Actor framework such as akka. Each actor is like a light weight thread in java and each actor has an inbox. so messaging is taken care of in this case.
So your scenario transforms to Friend 1 opens a connection to openfire xmpp server and initializes a Friend 1 Actor.When he types a message, it is transferred to the Friend 1 actor's in-box ( Each actor in akka has an in memory inbox). This is communicated to the xmpp server. The server has a database of its own, and since it is federated with other xmpp servers, it will try to find if friend 2 is online. The xmpp server will keep the message in its db until the friend 2 comes online. Once friend 2 establishes a connection to any of the xmpp server a friend 2 actor is created and its presence is propagated to all other servers and the xmpp server 1 will notify Friend 2's actor. Friend 2's actor inbox will now get the message
Optional: There is also a option of delivery receipt. Once Friend2 reads the message, a delivery receipt can be sent to friend 1 to indicate the status of the message i.e read, unread, delivered, not delivered etc.
Scenario 1 :
Setup a JMS Queue in your server
Java code to send Messages to Producer
Create a JMS Producer, which when invoked, should receive the email data (subject, body, to , cc etc) and post it to the Queue setup in step 1
Create a JMS Consumer, which subscribes to the Queue created in Step 1, and its onMessage should call the JavaMail API to send the email.
Scenario 2 :
Directly call the JavaMail API to send the email.
I know about how to use and what JMS and Java Mail are doing.Thing is why we have to go from Scenario 2 to Scenario 1 for sending mails.Initially we did Scenario 2.Now we are using Scenario 1.From Different parts of the Big Application are sending mails so we use JMS Queue ,there will be Consumer of Queue from there sending mails.Please help me to understand.
You would use this mechanism in a large application for 2 reasons:
1) You don't want your clients to have to wait for the mail to be sent.
2) You don't want to lose mails if you lose connectivity to your mail server for any reason.
You would do this if you don't have a relyable MTA near your local machine but need to be sure your mail will be send. For example if there is a network outage but you rely on Java Mail to send your mail without additional logic, your mail will not be send at all.
Using JMS you can reschedule the mail for transfer as soon as the real MTA will become available again.
Besides:
the conversation with the mail provider (SMTP und POP3) is
asynchronous and close to the JMS/MDB api. So why should i use a
different API than JMS ?
You can keep the mail handling in one transaction, together with some database changes other activities. I remember too many Spring .. sic' projects, where the customer demmands for a atomic operation, that included a state change in a db ;-)
Image, the messages you send become more compulsory and you have to connect to a X400 service. Simply think of the slight code change (and the change of the RA) and you will discover to met the right architectual descision.
First of all sorry for the long winded title but i was unable to think of a suitable title, considering my question.
Now to the problem. I am creating a peer to peer chat application, which has the ability to send and receive files while also being able to chat to individual contacts.
I understand i can capture the ip of the client connecting to the server and store this, then when that user starts a chat session to another person. I can use that stored ip to create a connection between the two clients using the ServerSocket.
BUT i do not wish to pass one users ip to another users computer for security reasons so, what i am asking basically is there a way to connect two clients together without passing each client each others ip.
so for e.g
(all sockets have read / write buffers )
Client 1-- logs in --> Server ( a session ID 1 is created between the client 1 and server )
Client 2-- logs in --> Server ( a session ID 2 is created between the client 2 and server )
Client 1 --- Starts chat with client 2 ---> Server ( server connects session 1 and session 2)
Client 1 can then chat and send files to client two without passing it the ip.
I am sorry if this is a unclear question or even stupid but i could not think of a way to even Google this question.
You would need to run the connection through a server. You could use the server to buffer the connection between the two clients and connect their communications in a way that would seem nearly seamless.
For example you could create a thread that, as long as both clients are connected, waits for input from client 1 and immediately pipes it to client 2. And the same would be necessary vice-versa. Is this the kind of solution you were looking for?
I have a application in which I am using socket programming , having this(image) scenario.
Where number of clients will try to connect Broadcast server.
Now here I am managing load through LVS(Load balancer). so as a example shown in image, suppose 200 clients will wish to login for broadcast they will be distributed as 100 users on server 1 and another 100 users on server 2.clients will get connected to servers using TCP connection.
Now I am maintaining user information on server side in arraylist which will be stored in heap memory,Now the problem is if client wish to broadcast to all logged in users, but that particular client is logged in server 1. and so client will not be able to broadcast another 100 users from server 2. Because both ther servers are unaware about each others state.
please suggest me to solve this scenario by whatever means you want.
Have the two servers log in to each other and arrange for broadcasts to be forwarded to the other server and then on to that server's clients.