Hành Trình Xây Hệ Thống Đạt Độ Chịu Tải Cho 10 Triệu Người Dùng Trên AWS
🏗️ Hành Trình Xây Hệ Thống Đạt Độ Chịu Tải Cho 10 Triệu Người Dùng Trên AWS
Từ zero tới production-grade system: một case study thực chiến cho những ai dấn thân vào thế giới kiến trúc hệ thống lớn.
🧠 1. Khởi nguồn: Vì sao cần scale tới 10 triệu người dùng?
Chúng tôi bắt đầu từ một MVP đơn giản: một ứng dụng di động phục vụ người dùng với chức năng giao tiếp thời gian thực, có user profile, phân quyền và dashboard quản lý. Sản phẩm dần phát triển, số lượng người dùng tăng nhanh chóng sau một chiến dịch viral thành công.
Vấn đề lớn nhất: hệ thống hiện tại không chịu nổi hơn 20K người online cùng lúc.
Mục tiêu đặt ra: xây lại hệ thống đủ để phục vụ được 10 triệu người dùng, với ít nhất 1 triệu concurrent user.
⚙️ 2. Kiến trúc ban đầu và những giới hạn
Kiến trúc ban đầu:
- Backend: Node.js monolith chạy trên 1 EC2 instance
- Database: MongoDB standalone
- Redis cho session và cache
- WebSocket server gắn trực tiếp với Node.js
- CI/CD: thủ công, dùng
scp
để deploy - Không có Auto Scaling, không có Load Balancer
Các vấn đề:
- Memory leak và CPU spike khi user online > 15K
- MongoDB query chậm dần vì không có phân vùng
- Không có cách nào mở rộng WebSocket horizontally
- Thời gian deploy lên tới 10 phút, dễ down hệ thống
- Không có observability (Prometheus, Grafana...)
🏗️ 3. Thiết kế lại kiến trúc hệ thống từ đầu
3.1. Triết lý thiết kế
- Stateless backend
- Horizontal scaling
- Async-first với message queue
- Event-driven architecture
- Polyglot persistence (dùng đúng DB cho đúng job)
3.2. Thành phần mới
Thành phần | Công nghệ |
---|---|
API Gateway | AWS API Gateway + Lambda |
Backend Core | NestJS chạy trên ECS Fargate |
Auth Service | Keycloak + OAuth2 |
WebSocket Gateway | Node.js + Redis Pub/Sub |
Database chính | MongoDB Cluster (Sharded) |
Search | OpenSearch |
Message Queue | Kafka |
Cache & Session | Redis Cluster |
File Storage | S3 |
CI/CD | GitHub Actions + CodePipeline |
Observability | Prometheus + Grafana + Loki |
Auto Scaling | ECS + Application Load Balancer |
Infrastructure as Code | Terraform |
☁️ 4. Sử dụng dịch vụ AWS một cách tối ưu
4.1. ECS Fargate vs EC2
ECS Fargate được chọn cho flexibility – không cần quản lý EC2, tự động scale, tích hợp tốt với VPC.
4.2. MongoDB Cluster
- Dùng MongoDB Atlas để tránh việc tự vận hành
- Sharding theo
userId
– giúp phân tán đều tải
4.3. Redis Cluster
- Redis được dùng cho:
- Session storage
- Rate limiting
- WebSocket Pub/Sub (đa vùng)
4.4. Kafka trên MSK
- Xử lý event-driven:
- Logging
- Notification
- Data sync sang ElasticSearch
4.5. CDN và bảo mật
- Sử dụng CloudFront + WAF cho layer bảo mật đầu tiên
- AWS Shield chống DDoS
🚀 5. Chiến lược scaling: từ 100K đến 10 triệu user
5.1. WebSocket Scaling
- Redis Pub/Sub để sync giữa các node
- Scale theo CPU và số lượng kết nối
- Load Balancer sticky session giảm reconnect
5.2. API Backend Scaling
- Stateless → scale vô hạn theo traffic
- Tối ưu query MongoDB, chỉ trả về dữ liệu cần thiết
- Dùng DataLoader để tránh n+1
5.3. Database scaling
- Sharding + index theo các field hay query
- Background job dọn log, archive data
5.4. CI/CD tối ưu
- GitHub Actions + CodePipeline:
- Tự động test, build, scan image
- Deploy canary trước khi rollout toàn bộ
📊 6. Giám sát & logging: trái tim của hệ thống production
- Prometheus: metric CPU, RAM, kết nối
- Grafana: dashboard real-time
- Loki: logging tập trung
- Alertmanager: cảnh báo qua Slack + Telegram
🧪 7. Testing: Không phải chỉ unit test là đủ
- Unit test: 95% coverage cho service quan trọng
- Integration test: dùng Testcontainers
- Load test: K6 để test WebSocket và API
- Chaos Engineering: simulate down Redis, Kafka...
🔁 8. Tối ưu chi phí: Không phải hệ thống mạnh là đắt
- Spot Instance cho job không cần uptime cao
- Scale down ban đêm bằng CloudWatch Alarm
- S3 lifecycle để tự xóa log cũ
- Compress WebSocket payloads bằng
zlib
🧠 9. Những bài học xương máu
- Đừng scale quá sớm, nhưng hãy chuẩn bị sớm
- Tránh coupling giữa các service
- Logging phải dễ truy vấn – log nhiều không bằng log đúng
- Không có observability = mù lòa khi production lỗi
- Cứ 2 tuần load test 1 lần – đừng để production là nơi test đầu tiên
🔚 10. Kết luận
Việc xây dựng hệ thống chịu được 10 triệu người dùng không phải là câu chuyện viển vông, nhưng cũng không phải là việc “click vài cái là xong”. Nó là sự kết hợp của tư duy hệ thống, công nghệ phù hợp, và vô số giờ refactor, test, monitor, tối ưu.
Nếu bạn đang trên hành trình tương tự – chúc bạn vững tay lái, kiến trúc vững chắc và đừng quên: log nhiều vào nhé!
Tham gia cuộc trò chuyện