The microservices architecture is a powerful approach to building scalable, maintainable, and deployable applications.
In microservices architecture, an application is composed of multiple, loosely-coupled services that can be developed, deployed, and scaled independently. Each microservice is responsible for a specific function and communicates with other services over the network, often through HTTP APIs or message brokers.
To build microservices, you’ll need to set up an environment where each microservice can operate independently. Start by creating a basic Express project for each service.
mkdir user-service order-service payment-service
For each service:
cd user-service
npm init -y
npm install express
user-service/server.js
)
const express = require('express');
const app = express();
app.use(express.json());
app.get('/', (req, res) => {
res.send('User Service');
});
const PORT = 3001;
app.listen(PORT, () => console.log(`User Service running on port ${PORT}`));
Repeat similar steps for the order-service
and payment-service
, configuring them to run on different ports.
When designing microservices, it’s important to consider:
Let’s create a simple User service to demonstrate microservice design.
user-service/server.js
)
const express = require('express');
const app = express();
app.use(express.json());
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
app.get('/users', (req, res) => {
res.json(users);
});
app.get('/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (user) {
res.json(user);
} else {
res.status(404).send('User not found');
}
});
const PORT = 3001;
app.listen(PORT, () => console.log(`User Service running on port ${PORT}`));
GET /users
: Returns a list of users.GET /users/1
: Returns user with id
1.This service handles user data and is responsible for user management only.
Microservices often need to communicate with each other. This can be done through:
axios
or node-fetch
).order-service
from user-service
npm install axios
user-service/server.js
)
const axios = require('axios');
app.get('/orders', async (req, res) => {
try {
const response = await axios.get('http://localhost:3002/orders');
res.json(response.data);
} catch (error) {
res.status(500).send('Order Service is unavailable');
}
});
Service discovery allows microservices to locate each other dynamically. In production environments, tools like Consul or Eureka can manage service discovery.
Each service can have a configuration file (config.js
) with the addresses of other services
In a microservices architecture, an API Gateway acts as a single entry point for clients to access multiple services.
http-proxy-middleware:
npm install http-proxy-middleware
gateway/server.js
)
npm install http-const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use('/users', createProxyMiddleware({ target: 'http://localhost:3001', changeOrigin: true }));
app.use('/orders', createProxyMiddleware({ target: 'http://localhost:3002', changeOrigin: true }));
const PORT = 3000;
app.listen(PORT, () => console.log(`API Gateway running on port ${PORT}`));
-middleware
Each microservice should ideally have its own database. This avoids tight coupling and allows each service to store data in a way best suited to its needs (e.g., NoSQL for one service, SQL for another).
Logging and monitoring are crucial in a distributed environment.
Docker and Kubernetes allow microservices to be containerized and managed at scale.
Dockerfile
for each service.k8s
for orchestration, deploying each service as a pod with its own configuration.Microservices with Express.js offers a scalable and modular way to build modern web applications. By breaking down an application into independent services, microservices provide flexibility in development, deployment, and scaling. Happy Coding!❤️