Skip to main content

Kiến trúc Microservices

Microservices chia ứng dụng thành nhiều service nhỏ, mỗi service phụ trách một năng lực nghiệp vụ, có codebase và dữ liệu riêng, được triển khai và mở rộng độc lập. Đổi lại là độ phức tạp của một hệ thống phân tán: mạng có thể lỗi, dữ liệu nằm rải rác, và vận hành cần tự động hóa cao.

So sánh các phong cách kiến trúc​

MonolithModular monolithMicroservices
Đơn vị triển khaiMộtMộtNhiều, độc lập
Mở rộngCả ứng dụngCả ứng dụngTừng service
Dữ liệuMột CSDL chungMột CSDL, chia schema theo moduleMỗi service một CSDL
Độ phức tạp vận hànhThấpThấpRất cao
Chịu lỗiThấp — một lỗi kéo sập cả appThấpCao — lỗi bị cô lập trong service
Linh hoạt công nghệMột stackMột stack, ranh giới module rõMỗi service tự chọn (polyglot)
Ưu điểmNhược điểm
Các đội phát triển và release độc lập, nhanh hơnĐộ phức tạp tăng vọt (mạng, phiên bản, debug)
Mở rộng đúng phần chịu tảiChi phí hạ tầng và vận hành cao
Lỗi được cô lậpKhó giữ dữ liệu nhất quán giữa các service
Tự do chọn công nghệ cho từng serviceĐòi hỏi văn hóa DevOps và kỹ năng cao
Codebase nhỏ, dễ hiểu cho từng độiBề mặt tấn công lớn hơn (nhiều endpoint, nhiều kết nối)
tip

Modular monolith thường là bước đầu tốt: ranh giới module rõ ràng giúp tách thành service sau này dễ hơn, mà chưa phải trả chi phí của hệ phân tán.

Khi nào nên chọn microservices?​

Chọn các tiêu chí đúng với dự án. CI/CD và DevOps trưởng thành là điều kiện tiên quyết — thiếu nó, microservices thường thành gánh nặng dù các tiêu chí khác đều đạt.

0%Chọn các tiêu chí đúng với dự án của bạn.

Hệ sinh thái​

Một hệ thống microservices không chỉ gồm các service nghiệp vụ mà còn cần nhiều thành phần hạ tầng hỗ trợ:

Thành phầnVai tròCông cụ phổ biến
ClientĐiểm bắt đầu của request. Không nên biết cấu trúc service phía sauWeb, mobile, hệ thống khác
API GatewayĐiểm vào duy nhất: định tuyến, xác thực, rate limiting, tổng hợp responseKong, NGINX, Spring Cloud Gateway
Application serviceMột năng lực nghiệp vụ (đơn hàng, thanh toán, kho), codebase và CSDL riêngBất kỳ stack nào
Message brokerGiao tiếp bất đồng bộ, event-driven giữa các serviceKafka, RabbitMQ, NATS
Service discoveryGiúp service tìm địa chỉ của nhau trong môi trường độngKubernetes Service (DNS có sẵn), Consul, Eureka
Config serverCấu hình tập trung cho mọi service và môi trường, đổi không cần deploy lạiSpring Cloud Config, Consul KV; secret dùng HashiCorp Vault
ObservabilityLog tập trung, metrics, distributed tracing với correlation IDELK stack, Prometheus + Grafana, OpenTelemetry

Ví dụ triển khai cụ thể: Spring Cloud, NestJS microservices.

Mẫu thiết kế cốt lõi​

MẫuGiải quyếtCách hoạt động
Database per serviceGhép nối ở tầng dữ liệuMỗi service sở hữu CSDL riêng; service khác chỉ truy cập qua API hoặc event. Mỗi service tự chọn loại lưu trữ phù hợp
API GatewayClient phải biết và gọi nhiều serviceMột điểm vào xử lý định tuyến, xác thực, rate limiting và có thể gộp dữ liệu từ nhiều service
Circuit breakerLỗi dây chuyền khi một service chậm hoặc sập3 trạng thái: Closed (gọi bình thường) → Open (từ chối ngay khi lỗi liên tục) → Half-open (thử lại vài lời gọi)
SagaGiao dịch trải trên nhiều service, không có ACID chungChuỗi transaction cục bộ; bước nào lỗi thì chạy transaction bù để hoàn tác các bước trước
CQRSĐọc và ghi có nhu cầu khác nhau, không JOIN được giữa các CSDLTách model ghi (command) và model đọc (query); model đọc là view phi chuẩn hóa, cập nhật từ event
Event sourcingCần lịch sử thay đổi đầy đủ, audit, truy vấn theo thời gianLưu mọi thay đổi trạng thái thành chuỗi event; trạng thái hiện tại có được bằng cách phát lại event

Vận hành và triển khai​

Microservices chỉ khả thi khi mọi bước từ commit đến production được tự động hóa:

  1. Commit — lập trình viên đẩy code lên một nhánh trong Git.
  2. CI (GitHub Actions, GitLab CI, Jenkins) — tự chạy build và unit test.
  3. Build & push image — đóng gói thành Docker image, gắn tag phiên bản, đẩy lên registry (Docker Hub, ECR, GHCR).
  4. Staging — tự triển khai image mới, chạy integration và end-to-end test.
  5. Production — sau khi duyệt, triển khai bằng chiến lược an toàn:
Chiến lượcCách làmĐánh đổi
RollingThay dần từng instance cũ bằng bản mớiĐơn giản; hai phiên bản chạy song song trong lúc triển khai
Blue/GreenDựng môi trường mới đầy đủ, chuyển traffic một lầnRollback tức thì; tốn gấp đôi hạ tầng trong lúc chuyển
CanaryChuyển một phần nhỏ traffic (ví dụ 5%) sang bản mới, tăng dần nếu metrics ổnAn toàn nhất; cần monitoring và định tuyến traffic tốt

Vì các service release độc lập, API giữa chúng phải tương thích ngược — xem API versioning.

Anti-pattern cần tránh​

Anti-patternDấu hiệuCách tránh
Distributed monolithSửa một tính năng phải deploy nhiều service cùng lúcChia theo bounded context, giao tiếp qua contract ổn định và event
Shared databaseNhiều service đọc/ghi chung bảngDatabase per service; chia sẻ dữ liệu qua API hoặc event
Chatty servicesMột request kéo theo hàng chục lời gọi đồng bộ nhỏGộp API theo use case, cache, chuyển sang event bất đồng bộ
NanoservicesSố service nhiều hơn số người trong độiGộp các service luôn thay đổi cùng nhau
Hardcoded configurationEndpoint, credential nằm trong codeConfig server, biến môi trường, secret manager
Bỏ qua observabilityKhông trả lời được "request này chậm ở service nào?"Log tập trung, metrics, distributed tracing ngay từ đầu