2

I am considering two alternatives for a chat application back-end architecture:

  • Server per room: where users connect to the same server, which forwards messages and other events directly. A database is used for persistence.
    • Pros: messages delivered faster, more efficient, less servers involved
  • Server per user: where each user connects to a server, which forwards messages and other events via a message broker (i.e. Redis) to other servers, which forward those events to users. Again, a database is used for persistence.
    • Pros: simple architecture, users connect to a single server, more reliable

Note: the term "server" refers to not a physical machine, but a specific address/port.

What other pros and cons exist for each model? Which model would I use in what situations? Are there any other possible back-end architectures?

In case this is relevant: the application focuses on 2-user rooms (i.e. direct messaging) with less emphasis on groups, or very large rooms.

If this isn't the right Stack Exchange network to ask on, please let me know and I can move the question. Thank you!

Luke
  • 2,038
  • 3
  • 22
  • 46

3 Answers3

5

Here somethings I want to point out for you:

  • Building a messaging app, I assume that you will use Websocket for sending and receiving messages, that means you will need sticky session which also means users are likely to connect to a single server every times they use the app
  • You definitely need a message broker too. Because without one, it would be very painful to get all your servers to communicate to each others. Redis is a good choice here, you could use it to cache user session too (faster than db), but still need to persist to db though
  • The idea of each users/rooms get their own "server" (address/port) is strange. Why do you need this? From my POV, it is pretty complicated. You would need to: direct users/rooms to their dedicated port, how to know their dedicated port, how to have multiple address per server? ...
kkkkkkk
  • 7,628
  • 2
  • 18
  • 31
  • Yes I'm using WebSockets to connect users to chat servers. I agree that Redis is needed for at least for some things, but the debate in my mind is whether or not messages should pass through Redis. I'll make my question a bit clearer; many users will be connected to the same address/port, but each will be assigned one (via a load balancer). The standard option seems to be for users to connect to one server, which handles everything from sending messages to profile updates. Another model I'm thinking of is having each room allocated to a server, and then users connect to those rooms (each po... – Luke Jun 09 '18 at 05:08
  • ...ssibly connecting to multiple servers) which forward messages *directly* to other users, instead of passing through remote nodes via Redis. I hope this make things more clear. – Luke Jun 09 '18 at 05:08
  • Using Redis is simpler and more reliable for your servers to communicate to each others. Without Redis, you would need to: keep track of which messages should go to which server, maintain multiples connections between servers, do error-handling when one of servers die or lag or simple does respond, figure out how to add or take out servers... – kkkkkkk Jun 09 '18 at 05:52
  • I just want to make clear that servers don't directly communicate with each other, but would be using Redis anyway. In my comment when I said "each possibly connecting to multiple servers", I meant each user, not server. The idea is to create a more direct link between users, instead of having their content pass through multiple servers (including Redis). – Luke Jun 09 '18 at 06:26
  • Honestly I agree; having one gateway per user is simpler, and probably more scalable. The architecture used by the big chat apps can't be too wrong. – Luke Jun 09 '18 at 06:34
0

I am missing the point of why you are trying to create different addresses and ports for each room (or what you refer to as server)

It could work like publisher/subscriber pattern for example. On a single server and single address, create a channel, which users (on single or group conversation) can listen to it. Then if a user publishes a message on that channel, you could send it to all subscribers.

Also there are different ways to handle message persistence, like first inserting them too the database then publishing them into channels. But as @Khang pointed out, there is a need for a broker. Your broker might be able to handle message persistence itself or it could just send messages from one server to another. (Nats for example)

Another thing is if you want to scale it up, your messages should be able to travel through your distributed network, like in situations when a channel subscriber is connected to different server; which still the broker you choose can help you in that.

But going back to pros and cons, Both solutions you talked about might end you up opening too many ports on too many addresses (If I understand it correctly) which does not seem to be ok, cause you could run out of them while a single port could handle everything you need. Also currently I have no idea how are you going to implement that. And it might not really make anything faster than other architectures.

Sepehr GH
  • 1,297
  • 1
  • 17
  • 39
  • Sorry that I didn't make it clearer. It's not like there's an address/port for every user, but an address/port is assigned to each user (with multiple sharing each port). In this model, to be scalable, clients may be connected to different servers, which must relay the messages. Is there a distributed message broker available? (i.e. one that sends published messages only to subscribing nodes) – Luke Jun 11 '18 at 07:26
  • I think redis does that too (havent tried yet), but I am completely sure NATS has a very good support of that feature. – Sepehr GH Jun 11 '18 at 09:40
0

One of the solutions for such is to use apache Kafka. You can build your backend to receive and publish chats(events) to a specific topic whose name will be the chat room id and every member that is part of the room will consume from it. (using the room id as the topic to listen to). Furthermore, you need another layer of persistence (preferably a NoSQL db) to store the chats.

Summary: Apache kafka sends the live events (notification) Springboot handles the backend React/Angular handles the frontend that serves as a consumer to the apache kafka instance.