A chat application based on a microservice architecture, with an interface built with Material UI and backend services deployed with Kubernetes (AWS EKS).
- Message pagination
- Real-time and multiple-device update of read flag, latest message, and unread count
(not auto synced if the network goes offline) - Side bar rendering conversations sorted by timestamp and updated in real-time
- Websocket client auto reconnection upon disconnection or network failure
- File uploads such as pdf, jpg, zip, etc.
- Image display as dialog
- Open new conversations with existing users
- Support online status
- Support conversation pagination
- Image compression for faster UI rendering
- Route Kafka pub/sub messsages to websocket servers that a receiver is connected to
- Support video display
account-service
: account registration, recovery, login, logout, profile-picture, metadatachat-service
: manage websockets connection, consume Kafka events and route to websocketsconversation-service
: create/list conversations, update latest messages & read timestamps of conversationsfile-upload-service
: file uploadmessage-service
: save/list messages, generate S3 presigned url, query unread counts
- grpc-spring for microservice communication
- Backend services run on Amazon Elastic Kubernetes Service
- Frontend built with Material UI
- Redis: login session
- Kafka: pub/sub system
- PostgreSQL: storage for user accounts, user metadata, and conversation metadata
- DynamoDB (AWS): storage for messages
- S3 (AWS): storage for images, files, and profile pictures
All AWS resources are operated at us-east-1
as an example.
-
Create a Redis cluster in the same VPC of your EKS cluster
-
Find the connection endpoint at Configuration Endpoint. Set the value in the
Secrets.yaml
.
https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/Endpoints.html -
Configure Security Group of the redis cluster to allow EKS nodes to connect to the redis cluster
Refer to Authorize access to the cluster
-
(optional) Set up connection to Redis cluster from outside VPC. Only required for local development.
https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/accessing-elasticache.html#access-from-outside-aws
-
Create a Kafka cluster in the same VPC of your EKS cluster.
-
Configure Security Group of the Kafka cluster to allow EKS nodes to connect to the Kafka cluster. For example, allow inbound traffic from the security group of EKS nodes.
-
Find Kafka bootstrap servers. Set the value in the
Secrets.yaml
. -
(optional) Set up connection to Kafka cluster from outside VPC. Only required for local development.
- Create a PostgreSQL database on AWS RDS.
- Configure Security Group of the database to allow EKS nodes to connect to the database.
- Find connection endpoint. Set the value in the
Secrets.yaml
. - (optional) Set public access to allow connection to RDS from outside VPC. Only required for local development.
- Open a S3 bucket. Set the bucket name in the
Secrets.yaml
. - Upload default profile pictures in
s3/profile-picture/default/
to S3 bucket under/profile-picture/default/
- Add CORS configuration to your bucket to allow presigned url. For example:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}
]
- Access S3 with AWS SDK.
Requirements:
- Node v16.16.0
- Java 17 (recommended)
Build React frontend
cd frontend
npm run build
Build Docker image for each microservice (Java)
cd account-service
./gradlew build
docker build --platform=linux/amd64 --tag swe99193/account-service .
docker push swe99193/account-service
cd chat-service
./gradlew build
docker build --platform=linux/amd64 --tag swe99193/chat-service .
docker push swe99193/chat-service
cd conversation-service
./gradlew build
docker build --platform=linux/amd64 --tag swe99193/conversation-service .
docker push swe99193/conversation-service
cd file-upload-service
./gradlew build
docker build --platform=linux/amd64 --tag swe99193/file-upload-service .
docker push swe99193/file-upload-service
cd message-service
./gradlew build
docker build --platform=linux/amd64 --tag swe99193/message-service .
docker push swe99193/message-service
Expected results:
- Access frontend at
https://xxxxxxxxx.cloudfront.net
(example) - Access backend at
http://k8s-default-instantc-xxxxxx-xxxxxx.us-east-1.elb.amazonaws.com/
(example)
Requirements:
- AWS S3
- AWS CloudFront
-
After building frontend, upload files under
/frontend/build
to S3 bucket and point a CloudFront distribution to the bucket.
Refer to How do I use CloudFront to serve HTTPS requests for my Amazon S3 bucket? -
Update permissions in S3.
Refer to Giving the origin access control permission to access the S3 bucket -
Create custom error response to direct all paths to
index.html
.
Requirements:
- kubectl
- eksctl
- AWS EKS
Create a new EKS cluster using public subnets in the default VPC
eksctl create cluster --name your-cluster --region us-east-1 --vpc-public-subnets subnet-xxxxxxxxxxxxxxxxx,subnet-xxxxxxxxxxxxxxxxx
❗️Check if these add-ons are installed: Amazon VPC CNI, CoreDNS, kube-proxy
Create an IAM OIDC provider for your cluster (required once)
https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html
Create an AWS Load Balancer Controller
https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html
Verify that AWS Load Balancer Controller is installed.
kubectl get deployment -n kube-system aws-load-balancer-controller
Add tags to the public subnets used by the cluster for LB to recognize subnets.
Refer to the Prerequisites section in Application load balancing on Amazon EKS
kubernetes.io/role/elb 1
Configure TLS certificates to allow https connection (Ingress
)
ref: https://repost.aws/knowledge-center/eks-apps-tls-to-activate-https
Tips: Create a self-signed certificate with the domain of ELB (e.g., k8s-default-instantc-xxxxxxx-xxxxxxx.us-east-1.elb.amazonaws.com) and import to AWS Certificate Manager.
Create your secrets k8/Secrets.yaml
(refer to Secrets-sample.yaml
)
FRONTEND_URL=https://xxxxxxx.cloudfront.net # configure CORS
Create the resources with yaml files
kubectl apply -f k8/Secrets.yaml
kubectl apply -f k8/Microservices-EKS.yaml
Check the created Ingress
kubectl describe ingress
Delete EKS cluster
eksctl delete cluster --name your-cluster --region us-east-1
Expected results:
- Access frontend at
https://yourchatdomain.com:3000
- Access backend at
https://yourchatdomain.com
Requirements:
- Node
Install packages and open React server
npm install
npm start
Requirements:
- minikube
- kubectl
Setup a local minikube cluster
minikube start
minikube addons enable ingress
Open external connection to minikube cluster
minikube tunnel
(optional) Open minikube dashboard
minikube dashboard
Add hostname mapping in /etc/hosts
on your local machine
127.0.0.1 yourchatdomain.com
Create your secrets k8/Secrets.yaml
(refer to Secrets-sample.yaml
)
FRONTEND_URL=https://yourchatdomain.com:3000 # configure CORS
Apply kubernetes configuration to create the resources
kubectl apply -f k8/Secrets.yaml
kubectl apply -f k8/Microservices-minikube.yaml
Delete minikube cluster
minikube delete
Retrieve EKS cluster context back to kubectl in case it somehow is gone.
aws eks update-kubeconfig --region us-east-1 --name your-cluster
Inspect logs
kubectl logs -f deployments/chat-deployment --tail=100
Restart deployment
kubectl rollout restart deployment
kubectl rollout restart deployment account-deployment