Kiến trúc Microservices với Docker và Message Queue
Design patterns microservices — phân rã service, giao tiếp async với RabbitMQ, circuit breaker, distributed tracing và observability.
Microservices cho phép deploy và scale độc lập từng component. Hướng dẫn này covers các pattern Ventra Rocket dùng trong production.
Khi nào nên dùng Microservices?
Dùng microservices khi:
- Các component có nhu cầu scale khác nhau
- Các team cần deploy độc lập
- Có ranh giới domain rõ ràng
Bắt đầu với monolith và tách ra khi ranh giới trở nên rõ ràng.
1. Phân rã Service
E-commerce
├── user-service — xác thực, hồ sơ
├── product-service — catalog, tồn kho
├── order-service — đơn hàng, giỏ hàng
├── payment-service — thanh toán
└── notification-service — email, SMS
2. Async Communication với RabbitMQ
import amqp from "amqplib";
// Publisher
async function publishOrderCreated(order: Order) {
const conn = await amqp.connect(process.env.RABBITMQ_URL!);
const channel = await conn.createChannel();
await channel.assertExchange("orders", "topic", { durable: true });
channel.publish("orders", "order.created",
Buffer.from(JSON.stringify(order)), { persistent: true });
}
// Consumer
channel.consume("notification.order.created", async (msg) => {
if (!msg) return;
const order = JSON.parse(msg.content.toString());
await sendOrderConfirmationEmail(order);
channel.ack(msg);
});
3. Circuit Breaker
class CircuitBreaker {
private failures = 0;
private state: "closed" | "open" | "half-open" = "closed";
private nextAttempt = Date.now();
async call<T>(fn: () => Promise<T>): Promise<T> {
if (this.state === "open" && Date.now() < this.nextAttempt) {
throw new Error("Circuit breaker open");
}
try {
const result = await fn();
this.failures = 0;
this.state = "closed";
return result;
} catch (err) {
this.failures++;
if (this.failures >= 5) {
this.state = "open";
this.nextAttempt = Date.now() + 30_000;
}
throw err;
}
}
}
4. Distributed Tracing
import { trace, SpanStatusCode } from "@opentelemetry/api";
async function createOrder(userId: string, items: OrderItem[]) {
return trace.getTracer("order-service").startActiveSpan("createOrder", async (span) => {
try {
const order = await db.orders.create({ userId, items });
span.setStatus({ code: SpanStatusCode.OK });
return order;
} catch (err) {
span.recordException(err as Error);
throw err;
} finally {
span.end();
}
});
}
Kết luận
Microservices phát huy hiệu quả khi domain đủ lớn để bù lại chi phí vận hành. Ventra Rocket đã migrate nhiều monolith sang microservices, đạt được chu kỳ deploy độc lập.
Bài viết liên quan
Hướng dẫn Deploy Node.js lên Kubernetes
Từng bước deploy Node.js lên Kubernetes — Deployments, Services, HPA, health checks, và zero-downtime rollouts.
Docker và CI/CD Pipeline cho ứng dụng Next.js
Hướng dẫn đầy đủ containerise ứng dụng Next.js với Docker multi-stage build và thiết lập CI/CD pipeline tự động với GitHub Actions.
CI/CD với GitHub Actions: Pipeline Build, Test và Deploy
Tự động hóa quy trình phát triển phần mềm với GitHub Actions — pipeline, testing, Docker build, deployment và quản lý secrets.