Monolith vs. Microservices: Mô hình tư duy 'Biệt thự vs Ngôi làng'
Microservices có phải chỉ là sự cường điệu (hype)? Hướng dẫn chuyên sâu về 'Distributed Monolith', cái giá của Latency, và khi nào thì thực sự nên tách service.
“Bọn em đang plan viết lại con Monolith này sang Microservices.”
Câu nói này đã bức tử nhiều startup hơn cả việc không tìm được thị trường (product-market fit).
Anh em Dev thích Microservices vì nó trông ngầu như Netflix. Sếp và Business ghét Microservices vì tính năng mới tự nhiên mất gấp 3 lần thời gian để dev.
Đây là Hướng dẫn chuyên sâu về Kiến trúc. Chúng ta sẽ tìm hiểu tại sao Monolith thường lại tốt hơn, và thời điểm chính xác bạn nên chuyển đổi.
Phần 1: Nền tảng (Mô hình tư duy)
Monolith = Căn Biệt thự Lớn
Tưởng tượng một Biệt thự khổng lồ nơi mọi người sống chung (Auth, Thanh toán, User, Đơn hàng).
- Giao tiếp: Tức thì. Đầu bếp cần Quản gia, gọi với một tiếng là xong. (Gọi hàm trong RAM: Nanoseconds).
- Database: Một cái tủ lạnh khổng lồ. Mọi người dùng chung nguyên liệu.
- Deploy: Bạn muốn sửa cái mái nhà? Phải đuổi tất cả mọi người ra ngoài 1 ngày để sửa. (Deploy lại toàn bộ app).
- Rủi ro: Nếu Bếp cháy, cả Biệt thự cháy rụi.
Microservices = Ngôi làng
Tưởng tượng một Ngôi làng gồm các ngôi nhà nhỏ riêng biệt.
- Giao tiếp: Chậm. Đầu bếp phải đi bộ sang nhà Quản gia để xin muối. (Gọi qua mạng: Milliseconds).
- Database: Mỗi nhà có một tủ lạnh mini riêng. Cấm sang nhà nhau lấy đồ.
- Deploy: Bạn sửa mái nhà ông Quản gia, ông Đầu bếp vẫn nấu ăn bình thường. Scale độc lập.
- Rủi ro: Nếu nhà bếp cháy, cả làng vẫn an toàn… nhưng giờ thì chẳng ai có cơm ăn.
Phần 2: Điều tra (Chi phí ẩn)
Chuyển sang Microservices không miễn phí. Bạn đang đánh đổi Sự phức tạp của Code lấy Sự phức tạp của Vận hành (Ops).
1. Thuế Latency (Độ trễ)
Trong Monolith, hàm UserService.getUser() tốn 0.0001ms (Truy cập RAM).
Trong Microservices, HTTP GET /users/1 tốn 20ms (Serialize mạng + TCP handshake + Latency đường truyền).
Bạn vừa làm cho thao tác cơ bản chậm đi 200,000 lần.
2. Ác mộng Truy vết (Tracing)
Trong Monolith, nếu lỗi, bạn xem Stack Trace. Nó báo chính xác dòng 42 bị lỗi.
Trong Microservices: Request -> Gateway -> Auth Service -> Order Service -> Payment Service (Lỗi). Log nằm ở đâu? Bạn phải lục tung 4 con server khác nhau để tìm.
- Giải pháp: Bắt buộc phải cài Distributed Tracing (OpenTelemetry/Jaeger). Không có nó là mù dở.
Phần 3: Chẩn đoán (Distributed Monolith)
Đây là kiểu kiến trúc tồi tệ nhất trần đời.
Nó xảy ra khi bạn xây một Ngôi làng, nhưng lại sống theo kiểu Biệt thự.
- Triệu chứng: “Em không deploy được Service A vì nó cần Service B update code trước.” (Coupling chặt).
- Triệu chứng: Service A chọc thẳng vào Database của Service B để lấy dữ liệu. (Phá vỡ quy tắc Tủ lạnh riêng).
- Triệu chứng: API call chằng chịt. Để load cái trang chủ, Frontend phải gọi 50 cái API tới 50 service.
Nếu service của bạn “Micro” (nhỏ) nhưng dính chặt vào nhau, bạn đã tạo ra một cục Distributed Monolith. Bạn gánh chịu toàn bộ sự chậm chạp của Microservices mà chẳng hưởng được tí lợi ích độc lập nào.
Phần 4: Giải pháp (Khi nào nên tách?)
Đừng tách vì kích thước (“Code base to quá rồi”). Hãy tách vì Nghiệp vụ (Domain).
Quy tắc Hai chiếc Pizza (Amazon)
Nếu một team quá đông, ăn 2 cái pizza không đủ, thì tách team. Sau đó hãy tách phần mềm để khớp với team đó.
Chiến thuật chia tách
- Luôn bắt đầu với Monolith. Nó giúp bạn đi nhanh giai đoạn đầu.
- Tách cái Nặng nhất trước.
- Module “Xử lý ảnh” ngốn 90% CPU? Tách riêng nó ra (Lambda/Worker).
- Giữ lại mọi thứ khác trong Monolith.
- Tách theo Vòng đời (Lifecycle).
- Module “Billing” (Thanh toán) chỉ sửa 1 năm 1 lần, nhưng “Frontend” sửa hàng ngày? Tách Billing ra để đỡ lỡ tay làm hỏng chức năng thu tiền khi đang sửa CSS.
Mô hình tư duy chốt hạ
Monolith -> Biệt thự. Nhanh, dễ chia sẻ, nhưng sợ sửa chữa lớn.
Microservices -> Ngôi làng. Giao tiếp chậm, bền vững, dễ sửa từng căn.
Distributed Monolith -> Ngôi làng mà mọi người bị còng tay vào nhau. Địa ngục trần gian.
Trừ khi bạn cần scale TỔ CHỨC (con người), hãy giữ lại MONOLITH (code). Bạn không phải Netflix. Bạn không cần rước cái khổ của Netflix vào thân làm gì.
Bài viết liên quan
-
Tại Sao Phần Cứng Rẻ Không Thể Giúp Redis Thay Thế Database Cốt Lõi
Khi phần cứng ngày càng rẻ, tại sao không dùng Redis làm cơ sở dữ liệu chính? Câu trả lời ngắn gọn: vì giới hạn không nằm ở tốc độ, mà nằm ở các yếu tố đảm bảo và ngữ nghĩa dữ liệu.
-
Caching & Redis: Mô hình tư duy 'Tờ giấy nhớ'
Tại sao Redis làm mọi thứ nhanh hơn? Hướng dẫn chuyên sâu về cache invalidation (vấn đề khó nhất CS), các chiến lược eviction, và Redis data types.
-
CDN: Mô hình tư duy 'Cửa hàng Tiện lợi'
Tại sao ảnh load ngay với user Mỹ nhưng ì ạch ở Việt Nam? Hướng dẫn chuyên sâu về CDN Edge Node, Cache-Control header và cache busting.
-
Task Queue & Message Broker: Celery, RabbitMQ và Kafka — Phân biệt rõ ràng
Tại sao gửi email làm đứng API? Hướng dẫn chuyên sâu về xử lý bất đồng bộ: từ Celery/Django-Q (hàng đợi tác vụ) đến RabbitMQ (môi giới) và Kafka (luồng sự kiện).