Microservices Architecture
"Microservices are small, autonomous services that work together." — Sam Newman, Building Microservices
Microservices Architecture là một phương pháp kiến trúc phần mềm nơi một ứng dụng được cấu thành từ nhiều dịch vụ nhỏ, độc lập, mỗi dịch vụ chạy trong tiến trình riêng và giao tiếp qua các giao thức nhẹ (thường là HTTP/REST hoặc message queue). Mỗi microservice được xây dựng xoay quanh một business capability cụ thể, có thể được triển khai, mở rộng, và bảo trì độc lập với các service khác. Đây là một trong những kiến trúc có ảnh hưởng nhất trong thập kỷ qua — được áp dụng bởi Netflix, Amazon, Spotify, Uber, và hầu hết các công ty công nghệ hàng đầu thế giới.
Bài toán
Vấn đề: Khi monolith trở thành gánh nặng
Hãy tưởng tượng bạn đang làm việc cho một nền tảng thương mại điện tử lớn — giống như Shopee, Tiki, hay Lazada. Hệ thống bắt đầu như một monolith: một codebase duy nhất, deploy như một ứng dụng duy nhất. Khi công ty còn nhỏ (vài chục nghìn user, đội ngũ 5-10 developers), monolith hoạt động hoàn hảo. Nhưng khi công ty phát triển, monolith bắt đầu bộc lộ những vấn đề nghiêm trọng:
1. Development bottleneck: Một monolith với 2 triệu dòng code, 200 developers làm việc trên cùng một repository. Merge conflict là nỗi ám ảnh hàng ngày. Mỗi pull request mất 3-5 ngày để review vì phải hiểu toàn bộ hệ thống. Feature branch có thể sống sót hàng tuần trước khi được merge.
2. Scaling inefficiency: Module search (CPU-bound) và module payment (I/O-bound) có nhu cầu scaling hoàn toàn khác nhau. Với monolith, bạn phải scale toàn bộ ứng dụng — kể cả những phần không cần thiết. Bạn trả tiền cho server chạy module forgot-password trong khi module search đang quá tải.
3. Technology lock-in: Bạn muốn thử nghiệm một công nghệ mới? Muốn dùng Python cho AI recommendation service, Go cho real-time chat, Java cho payment processing? Với monolith, bạn chỉ có một lựa chọn. Công nghệ bạn chọn năm 2018 (PHP + MySQL + Memcached) vẫn là công nghệ bạn phải dùng năm 2025.
4. Reliability cascade: Bug trong module product listing (hiển thị sản phẩm) làm sập toàn bộ ứng dụng — kể cả module checkout và payment. Một lỗi nhỏ trong phần không quan trọng có thể kéo sập toàn bộ hệ thống, gây thiệt hại hàng triệu đô la.
5. Scaling the team is hard: Quy tắc của Conway: "Hệ thống sẽ phản ánh cấu trúc giao tiếp của tổ chức." Một monolith với 200 developers không thể hoạt động hiệu quả. Giao tiếp giữa các team trở nên hỗn loạn. Không ai thực sự "sở hữu" module nào. Trách nhiệm mờ nhạt.
Giải pháp từ Microservices
Microservices giải quyết tất cả các vấn đề trên bằng cách chia nhỏ monolith thành nhiều service độc lập, mỗi service:
- Owned by một team (thường 3-8 developers) — team có toàn quyền quyết định về công nghệ, database, cách triển khai
- Single responsibility — mỗi service làm một việc và làm tốt việc đó
- Independently deployable — team có thể deploy service của mình mà không cần phối hợp với team khác
- Independently scalable — mỗi service có thể scale theo nhu cầu riêng
- Failure isolated — service A sập không kéo theo service B sập
Hãy xem xét một ví dụ cụ thể. Khi user tìm kiếm "iPhone 15" trên nền tảng thương mại điện tử, hành trình request đi qua nhiều service:
User → API Gateway →
1. Search Service (tìm kiếm sản phẩm)
2. Product Service (lấy thông tin chi tiết)
3. Inventory Service (kiểm tra tồn kho)
4. Pricing Service (tính giá + khuyến mãi)
5. Recommendation Service (sản phẩm gợi ý)
6. Review Service (đánh giá, xếp hạng)
7. User Service (thông tin user, loyalty points)
Mỗi service này do một team riêng phụ trách, có database riêng, có thể scale riêng, và có thể fail riêng mà không ảnh hưởng đến các service khác.
Nguyên lý thiết kế
1. Single Responsibility per Service
Mỗi microservice nên tập trung vào một business capability duy nhất. Tiêu chí xác định ranh giới service:
- Data ownership: Service sở hữu dữ liệu của nó. Không share database giữa các service.
- Business domain: Xoay quanh một bounded context trong DDD (Domain-Driven Design)
- Change reason: Service chỉ thay đổi vì một lý do duy nhất — thay đổi trong business capability của nó
- Team size: Service vừa đủ để một team (3-8 người) có thể hiểu và maintain
2. Decentralized Data Management
Mỗi microservice có database riêng (Database-per-Service pattern). Điều này khác hoàn toàn với monolith nơi mọi module đều dùng chung một database. Hệ quả:
- Data consistency: Không có ACID transaction xuyên service. Phải dùng eventual consistency và saga pattern.
- Data duplication: Một số dữ liệu có thể được duplicate giữa các service (ví dụ: Product Service có thông tin sản phẩm, Search Service cũng có index riêng).
- Data synchronization: Dùng event-driven để đồng bộ dữ liệu giữa các service.
3. Communication Patterns
Có hai mô hình giao tiếp chính:
Synchronous (Request-Response):
- HTTP/REST hoặc gRPC
- Đơn giản, quen thuộc
- Vấn đề: Coupling giữa các service, cascading failure
- Dùng khi: Cần response ngay lập tức, query data
Asynchronous (Event-Driven):
- Message queue (RabbitMQ, Kafka)
- Decoupling cao, chịu lỗi tốt
- Vấn đề: Eventually consistency, debugging khó
- Dùng khi: Cần broadcast event, eventual consistency chấp nhận được
4. API Gateway Pattern
Một gateway duy nhất đứng trước tất cả microservices, đảm nhận:
- Routing: Định tuyến request đến đúng service
- Authentication: Xác thực tập trung
- Rate limiting: Giới hạn request
- Load balancing: Phân phối request
- Aggregation: Gọi nhiều service và aggregate response
- Protocol translation: REST → gRPC, HTTP → WebSocket
5. Service Discovery
Trong môi trường container (Kubernetes, Docker Swarm), service có thể được tạo và hủy động. Cần cơ chế discovery:
- Client-side discovery: Client (service consumer) tự query service registry
- Server-side discovery: Load balancer (API Gateway) biết vị trí của service
6. Resilience Patterns
| Pattern | Mô tả | Library |
|---|---|---|
| Circuit Breaker | Ngăn gọi service đang lỗi, fail fast | Hystrix, resilience4j, pybreaker |
| Retry with Backoff | Thử lại khi lỗi tạm thời, có exponential backoff | tenacity (Python) |
| Bulkhead | Cô lập tài nguyên (thread pool riêng cho mỗi service) | ThreadPoolExecutor riêng |
| Timeout | Giới hạn thời gian chờ response | asyncio timeout, HTTP timeout |
| Fallback | Trả về default/dummy data khi service lỗi | Cache, default value |
7. Observability
Với nhiều service phân tán, observability là bắt buộc:
- Distributed Tracing: Theo dõi request xuyên suốt các service (Jaeger, Zipkin)
- Centralized Logging: Tất cả log về một chỗ (ELK Stack: Elasticsearch, Logstash, Kibana)
- Metrics: Prometheus + Grafana cho monitoring
- Health Checks: Endpoint
/healthmỗi service, readiness + liveness probes - SLA Monitoring: Uptime, latency, error rate theo service
Cấu trúc chi tiết
High-Level Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ CLIENT LAYER │
│ Web App │ Mobile App │ Third-Party API │
└──────────────────────────────┬──────────────────────────────────────┘
│
▼
┌────────────────────────────────── ───────────────────────────────────┐
│ API GATEWAY │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Auth │ │ Route │ │ Rate │ │ Cache │ │ Log │ │
│ │ Middle. │ │ Engine │ │ Limiter │ │ │ │ Middle. │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└────────────────────────────────┬─────────────────────────────────────┘
│
┌───────────────────────┼──────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Product │ │ Order │ │ User │
│ Service │ │ Service │ │ Service │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ - Product CRUD │ │ - Cart mgmt │ │ - Auth (JWT) │
│ - Category mgmt │ │ - Checkout │ │ - Profile mgmt │
│ - Search index │ │ - Payment │ │ - Address mgmt │
│ │ │ - Shipping │ │ - Loyalty points │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ Database: MySQL │ │ Database: Postgres│ │ Database: MongoDB│
└──────────────────┘ └──────────────────┘ └──────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ MESSAGE BROKER (Kafka / RabbitMQ) │
│ Topics: product.created │ order.placed │ payment.completed │ ... │
└─────────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌────────────── ────┐ ┌──────────────────┐ ┌──────────────────┐
│ Notification │ │ Analytics │ │ Recommendation │
│ Service │ │ Service │ │ Service │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ - Email │ │ - Event tracking │ │ - ML model │
│ - SMS │ │ - Report gen │ │ - Product rec │
│ - Push notif. │ │ - Real-time dash │ │ - Personalization│
└──────────────────┘ └──────────────────┘ └──────────────────┘
Service Structure (per service)
product-service/
├── Dockerfile # Container build
├── requirements.txt # Dependencies
├── pyproject.toml # Python project config
├── tests/
│ ├── __init__.py
│ ├── conftest.py
│ ├── test_api.py # HTTP endpoint tests
│ ├── test_service.py # Business logic tests
│ └── test_repository.py # Data access tests
├── src/
│ ├── __init__.py
│ ├── main.py # FastAPI app + startup
│ ├── config.py # Service configuration
│ ├── domain/
│ │ ├── __init__.py
│ │ ├── models.py # Domain entities
│ │ ├── events.py # Domain events
│ │ └── exceptions.py # Service exceptions
│ ├── application/
│ │ ├── __init__.py
│ │ ├── service.py # Use cases
│ │ └── interfaces.py # Ports (repositories, messaging)
│ ├── infrastructure/
│ │ ├── __init__.py
│ │ ├── api/ # HTTP controllers
│ │ │ ├── __init__.py
│ │ │ ├── routes.py
│ │ │ ├── serializers.py