Microservices
microservices
This repository contains a backend system for a social media platform, built using a microservices architecture. The project demonstrates the principles of breaking down a monolithic application into smaller, independently deployable services that communicate with each other over the network. The system is designed to be scalable, maintainable, and resilient.
Architecture Overview
The system is composed of five main services, each with a distinct responsibility. An API Gateway acts as the single entry point for all client requests, routing them to the appropriate downstream service. Communication between services is handled asynchronously using a RabbitMQ message broker, promoting loose coupling and enabling an event-driven architecture.
- API Gateway: The client-facing entry point. It handles request routing, authentication (JWT validation), rate limiting, and basic security.
- Identity Service: Manages all aspects of user identity, including registration, login, and token management (access and refresh tokens).
- Post Service: Responsible for creating, reading, and deleting user posts. It publishes events to RabbitMQ when posts are created or deleted.
- Media Service: Handles the upload and management of media files. It integrates with Cloudinary for storage and listens for
post.deletedevents to perform media cleanup. - Search Service: Provides full-text search capabilities for posts. It consumes
post.createdandpost.deletedevents to keep its search index synchronized.
Technology Stack
- Backend: Node.js, Express.js
- Database: MongoDB with Mongoose ODM
- Caching: Redis
- Message Broker: RabbitMQ
- Media Storage: Cloudinary
- Authentication: JSON Web Tokens (JWT), Argon2 for password hashing
- Containerization: Docker
Services
1. API Gateway
- Responsibility: Acts as a reverse proxy, routing incoming requests to the correct microservice. It is the sole entry point for the frontend.
- Features:
- JWT validation for protecting routes.
- Rate limiting using Redis to prevent abuse.
- Request logging and error handling.
- Proxies requests to
identity-service,post-service,media-service, andsearch-service.
2. Identity Service
- Responsibility: Manages user accounts and authentication.
- Features:
- User registration with username, email, and hashed password (Argon2).
- User login and generation of JWT access and refresh tokens.
- Refresh token rotation and secure storage.
- User logout, which invalidates the refresh token.
3. Post Service
- Responsibility: Manages the lifecycle of user posts.
- Features:
- CRUD operations for posts (Create, Read, Delete).
- Caches post data in Redis to reduce database load.
- Publishes
post.createdandpost.deletedevents to RabbitMQ.
4. Media Service
- Responsibility: Handles media file uploads and storage.
- Features:
- Uploads files (images, videos) to Cloudinary.
- Uses
multerfor handling multipart/form-data. - Subscribes to
post.deletedevents to delete associated media from Cloudinary, preventing orphaned files.
5. Search Service
- Responsibility: Provides search functionality across all posts.
- Features:
- Subscribes to
post.createdandpost.deletedevents to maintain a consistent search index. - Uses MongoDB’s native text search capabilities to index and query post content.
- Subscribes to
Event-Driven Communication
The services communicate asynchronously through a facebook_events exchange in RabbitMQ.
post.created: Published by the Post Service when a new post is created. It is consumed by the Search Service to add the new post to its search index.post.deleted: Published by the Post Service when a post is deleted. It is consumed by:- The Search Service to remove the post from its index.
- The Media Service to delete any associated media files from Cloudinary.
Setup and Running the Project
Each service is containerized using Docker. To run the entire application, you will need Docker, Node.js, and npm installed.
Environment Variables
Before running, create a .env file in the root directory of each service (api-gateway, identity-service, etc.). Populate them with the necessary configuration.
Common Variables
MONGO_URI: Your MongoDB connection string.RABBITMQ_URL: Your RabbitMQ connection string.REDIS_URL: Your Redis connection URL.PORT: The port for the service to run on (e.g., 3001, 3002).
Service-Specific Variables
- api-gateway/.env:
JWT_SECRET: Secret key for JWT signing.IDENTITY_SERVICE_URL=http://localhost:3001POST_SERVICE_URL=http://localhost:3002MEDIA_SERVICE_URL=http://localhost:3003SEARCH_SERVICE_URL=http://localhost:3004
- identity-service/.env:
JWT_SECRET: Secret key for JWT signing (must match the gateway’s).
- media-service/.env:
CLOUDNAME: Your Cloudinary cloud name.API_KEY: Your Cloudinary API key.API_SECRET: Your Cloudinary API secret.
Running with Docker
For each service, navigate to its directory and run the following commands:
# Example for api-gatewaycd api-gateway
# Build the Docker imagedocker build -t api-gateway .
# Run the Docker container# Replace 3000 with the port you want to exposedocker run -p 3000:3000 --env-file .env api-gatewayRepeat this process for all other services (identity-service, post-service, media-service, search-service), ensuring you map the correct ports as defined in your environment files.
Running Locally (without Docker)
For each service, navigate to its directory and run:
# Example for api-gatewaycd api-gateway
# Install dependenciesnpm install
# Run in development mode (with nodemon)npm run dev
# Or run in production modenpm startAPI Endpoints
All endpoints are accessed through the API Gateway and are prefixed with /v1.
Identity Service (/v1/auth)
POST /register: Register a new user.POST /login: Log in a user and receive access/refresh tokens.POST /refresh-token: Obtain a new access token using a refresh token.POST /logout: Log out a user.
Post Service (/v1/posts)
All routes require authentication.
POST /create-post: Create a new post.GET /all-posts: Get a paginated list of all posts.GET /:id: Get a single post by its ID.DELETE /:id: Delete a post.
Media Service (/v1/media)
All routes require authentication.
POST /upload: Upload a media file. Expectsmultipart/form-datawith a field namedfile.
Search Service (/v1/search)
All routes require authentication.
GET /posts?query=<search_term>: Search for posts matching the query term.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Share Article
If this article helped you, please share it with others!