Vartalap: Chat Server Architecture

This is second blog post is part of series of blog posts, where I will be sharing details about Vartalap how it started, decision I make while developing it, technical details, problem with current system and how I am planning to solves it. In this blog I will be sharing existing backend server architecture. If you haven’t already read the first blog, I highly recommend reading that. Link to first blogpost on medium or here (Vartalap: Open Source Personal Messaging App).

If you had read the previous blog post, you known that Vartalap is started as a learning project for Kafka and to test my skills to architect a system. Before starting architecting that system, Always the first step will be the note down the functional and non-functional requirement. Writing down the requirements gives the better picture what do we need to architect. One thing which is there in my mind to I am not going to build the complete system in one go, So I selected few of the minimal requirement which is should be there so make the application useable or the MVP product.

Functional Requirement

  • Login with mobile number.
  • 1 to 1 and group rich text messaging (Supports emoticons).
  • Contact list.
  • Offline availability.
  • Can receive message when user existed the app.
  • Messages shouldn’t be stored on the server forever.

Non-Functional Requirement

  • Real time message delivery
  • Scalable
  • Highly available
  • Fault tolerance
  • Data integrate

Architecture

After doing few iteration of working on the architecture, finally I settled with this one.

It’s an microservice based architecture where system is divided into small groups of individual service responsible to handling a particular feature of the system. The advantage of having microservice architecture are

  • No single point of failure improves the system fault tolerance.
  • Can easily scale the specific part of the system which ever is needed.
  • Can easily upgrade/replace the any part of the system without bringing whole system down.
  • Deploying the system parts as it builds instead of waiting for complete system to go up.

In fact due the microservices it helps me motivated to build the system. Instead of waiting to bring the whole system up, I work on particular parts in my free time then deployed it and share it with friends and family members. Continuous feedback from them keeps me motivated but continue the development.

Find the source code on GitHub at chat server

Components

  • Nginx as API gateway
  • Kafka as Message brokers
  • Mongodb as database
  • Firebase for push notification
  • Redis as cache store
  • Nodejs for microservices

Services

List of microservices and responsibility:

Profile service

Responsibility

  • Login
  • Auth
  • Contact Sync

Web Socket Gateway

Responsibility

  • Maintaining Web Socket Connection
  • Forwarding socket event like onConnect, onDisconnect, onMessage to message broker (Kafka)
  • Sending message back to client

Session MS

Responsibility

  • Maintain User connection state

Message Router

Responsibility

  • Route 1-to-1 chat message to gateway
  • Route message to store/push notification
  • Retry failed message
  • Route group message to Group Message Router

Push Notification

Responsibility

  • Deliver message to offline user

Persistence Storage service

Responsibility

  • Store message new user is offline
  • Deliver message as user come online

Group MS

Responsibility

  • Create Group
  • Add, Remove Members
  • Fetch groups

Group Message Router

Responsibility

  • Route Group Message to respective destination

Request flows

Authentication

Client Side:

  • User login/signup with mobile number
  • Send OTP using firebase authentication service
  • Verify OTP using firebase authentication service
  • Get firebase authentication token
  • Send firebase authentication token to profile service for login

Server Side:

  • Verify firebase authentication token
  • Check if it’s a new user then signup
  • Generate authentication token
  • Publish event for new login
  • Return authentication token
  • Push Notification service listen to new login event
  • Update the FCM token against the user

Startup

Client Side:

  • Web socket connection request.
  • Contact Sync request.

Server Side (Web socket):

  • Nginx authenticates via issuing sub-request to profile ms for auth.
  • Nginx forward request to web socket gateway.
  • Fetch user info for request header.
  • Gateway accepts the upgrade connection requests.
  • Raise event for onConnect to message brokers.
  • Store web socket connection against users.
  • Session ms listen for onConnect event and store information of user and gateway mapping
  • Persistence ms listen for onConnect event and fetch all the pending messages
  • Publish onMessage event for the user.
  • Delete all the stored messages.

Server Side (Sync request):

  • Nginx authenticates via issuing sub-request to profile ms for auth.
  • Nginx forward request to profile ms for contact sync.
  • Profile ms verify the registered users from list of contacts in payload.
  • Returns list of app users from contacts in payload.

Send Message (1 to 1)

Client Side:

  • Send message against a chat
  • Store message against chat in local store
  • Publish message to web socket.

Server Side:

  • Gateway publish onMessage event to message broker to meta info like from.
  • Message router listen for onMessage.
  • Parse the message and extract destination information.
  • Call session ms for gateway server against the user.
  • If user is connected.
  • Publish message to message broker against gateway server topic (generally the name of the server).
  • Gateway server listen for it’s topic and tries to send message to user socket.
  • If failed, publish message for failed message which will be against consumed by message router and follow same steps.
  • If user is not connected.
  • Publish message to offline message.
  • Push notification ms listen for offline message and send push notification.
  • Persistence ms listen for offline message and store in the database until user comes online.

Group Chat

Create New Group

Client Side:

  • Choose the participants and group name.
  • Send http request to create group.

Server Side:

  • Nginx authenticates via issuing sub-request to profile ms for auth.
  • Nginx forward request to group ms.
  • Group ms validate the participants
  • Create a new group
  • Publish new groupMessage for participants.
  • Returns groupId.
  • Group Message router, fetch the connected gateway server info from session ms.
  • Publish message to gateway topic. (Further flow will be same as 1 to 1 chat).
  • For offline message published to offline message.(Further flow will be same as 1 to 1 chat).

Update Group

Client Side:

  • Choose participants to add or remove.
  • Send http request for add or remove.

Server Side:

  • Nginx authenticates via issuing sub-request to profile ms for auth.
  • Nginx forward request to group ms.
  • Group ms validate the participants
  • Update the group
  • Publish new groupMessage for participants.
  • groupMessage will be handled similar to Create New Group.

Send Message (Group Message).

Client Side:

  • Send message against a chat
  • Store message against chat in local store
  • Publish message to web socket.

Server Side:

  • Gateway publish onMessage event to message broker to meta info like from.
  • Message router listen for onMessage.
  • Parse the message and extract destination information.
  • Publish message to groupMessage.
  • groupMessage will be handled similar to Create New Group.

Limitation of Current Architecture

  • No proper acknowledgement system for message delivery.
  • Only web socket gateway for events, making it difficult for background event syncing.
  • Router publishing directly into gateway topic, making message delivery logic to be duplicated among services.
  • Group operations are synchronous making it not useable offline.
  • Base message template for events.

To overcome the limitation of current system I am working on the second version of the system. Details of which I’ll be sharing on the next blog post.

Link to Vartalap Architecture V2 here or medium article

Note: This blog is originally published on blog.one9x.org

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Laravel 8 Add Watermark on Image

Google Summer of code at Debian Final Report

Cucumber Founder Aslak Hellesøy on TDD and BDD

How to develop for Oculus Quest on macOS with Unity

Introduction to Spring Framework

I just participated in InsureDAO testnet.

Project Update: Player setup

Why I am trying to code myself out of a job

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Raman kumar

Raman kumar

More from Medium

Multiple image upload using SimpleS3 to AWS s3 bucket using flutter.

Deploy Node App in 4 EASY Steps Using Caddy

Firebase: Troubleshooting “The default Firebase app does not exist…”

How to host multiple servers with different sub domains inside one DigitalOcean droplet with SSL…