Kiến trúc Modular Monolith Phần 1 - Giới thiệu về Modular Monolith

Trong giới lập trình, cứ vài tháng là lại rộ lên một trend mới. Ai cũng hừng hực làm theo, như thể không theo là tụt hậu. Một trong những trend nổi tiếng và được nhắc đến suốt mấy năm nay là Microservices. Cứ nghe đến Netflix, Amazon hay Uber là người ta nghĩ ngay: "À, mấy ông đó dùng Microservices, chắc mình cũng làm vậy cho pro!". Và thế là không ít team từ startup nhỏ cho tới các dự án nội bộ cũng bắt đầu chia nhỏ ứng dụng ra thành cả đống service dù chưa hiểu hết lý do tại sao.

Nhưng không phải dự án nào cũng cần Microservices. Nếu chọn sai kiến trúc, bạn sẽ phải trả giá đắt.

Hãy cùng tôi khám phá một lựa chọn khác không kém phần mạnh mẽ nhưng khôn ngoan hơn, đó chính là Modular Monolith. Kiến trúc này là sự cân bằng giữa sức mạnh và sự đơn giản.

Monolith – Một khối duy nhất

Hãy tưởng tượng bạn đang xây một căn nhà cấp 4. Mọi thứ từ phòng khách, phòng ngủ đến nhà bếp tất cả đều nằm trong cùng một khối nhà. Dễ xây, dễ sửa, dễ quản lý. Kiến trúc Monolith cũng giống như vậy. Tất cả logic, chức năng nằm trong cùng một codebase, chạy trong một process duy nhất. Khi deploy, bạn chỉ cần build một lần, upload một lần là xong. Ghi log, xử lý transaction cũng dễ vì mọi thứ đều ở chung.

Nhưng khi nhà bạn bắt đầu đông người thì việc chỉnh sửa ngôi nhà sẽ bắt đầu phát sinh nhiều vấn đề. Bạn muốn đập tường sửa lại nhà bếp, nhưng lại phải ngắt điện cả nhà. Trong phần mềm cũng y hệt:

  • Khi ứng dụng lớn lên, codebase trở nên rối rắm, các thành phần phụ thuộc lẫn nhau, sửa chỗ này dễ ảnh hưởng đến nhiều chỗ khác.
  • Thêm tính năng mới trở nên khó khăn vì phụ thuộc lẫn nhau quá nhiều.
  • Khi lượng người dùng tăng lên, buộc phải scale toàn bộ ứng dụng dù thực tế chỉ một phần cần nhiều tài nguyên hơn. Ví dụ, nếu chỉ có tính năng thanh toán cần phục vụ nhiều người dùng, ta vẫn phải scale toàn bộ ứng dụng thay vì chỉ phần thanh toán.

Microservices - Chia nhỏ mọi thứ

Trước những hạn chế của Monolith, người ta nghĩ ra Microservices. Kiến trúc này chia ứng dụng thành các service nhỏ, độc lập, mỗi cái chịu trách nhiệm cho một việc cụ thể, chạy trên process riêng, có thể dùng ngôn ngữ và database khác nhau. Điều này mang lại nhiều lợi ích:

  • Mỗi team có thể chọn công nghệ phù hợp, phát triển và release mà không cần chờ đợi các team khác.
  • Dễ dàng scale từng dịch vụ riêng dựa trên nhu cầu thực tế.
  • Một dịch vụ gặp sự cố không làm ảnh hưởng đến toàn bộ hệ thống (tăng tính sẵn sàng và chịu lỗi).

Tuy nhiên, Microservices cũng không phải là "viên đạn bạc". Nó mang theo nhiều rắc rối khác:

  • Thay vì một codebase, ta phải quản lý nhiều cái, dẫn đến phức tạp trong việc quản lý phiên bản, deploy, monitor. Việc debug cũng trở nên khó khăn hơn.
  • Để hệ thống chạy ổn định, bạn cần một hạ tầng mạnh và đội DevOps chắc tay phải biếtđủ thứ như Docker, Kubernetes, Service Mesh, Distributed Tracing, Circuit Breaker... và ti tỉ thứ khác.

Microservices chỉ phát huy khi ứng dụng của bạn thật sự đủ lớn.

Modular Monolith - Giải pháp cân bằng

Giờ tưởng tượng khác đi: Bạn có một chung cư mini, bên ngoài là một tòa nhà duy nhất, nhưng bên trong chia thành nhiều căn hộ riêng biệt. Mỗi căn hộ có cửa riêng, nội thất riêng, không ảnh hưởng tới nhau, nhưng tất cả vẫn nằm trong cùng một tòa nhà. Đó chính là Modular Monolith.

Modular Monolith là một ứng dụng được build và deploy như một khối duy nhất (single deployable unit), nhưng được chia thành nhiều module độc lập về mặt nghiệp vụ (business modules). Mỗi module chỉ giao tiếp với nhau qua interface hoặc event, không trực tiếp gọi vào code của module khác. Có thể được phát triển, test và maintain tương đối độc lập, nhưng vẫn được build và deploy cùng nhau.

Về bản chất, Modular Monolith vẫn là Monolith, nhưng được thiết kế theo tư duy Microservices, tức là bạn tổ chức code như thể nó đã tách, chỉ khác ở chỗ nó vẫn chạy trong một process duy nhất.

Nếu tổ chức code tốt, sau này bạn thậm chí có thể bóc tách từng module ra thành Microservice thật mà không cần viết lại toàn bộ.

Tại sao nên chọn Modular Monolith?

Với đa số dự án nhỏ hoặc vừa, Modular Monolith là lựa chọn cực hợp lý. Nó giúp bạn giữ code sạch, dễ quản lý, dễ mở rộng, mà không phải lao đầu vào rừng công nghệ như Kubernetes hay Kafka ngay từ đầu. Bạn có thể tập trung vào logic nghiệp vụ thay vì hạ tầng, dễ dàng chuyển đổi sang Microservices khi ứng dụng đủ lớn mà vẫn tận dụng được đầy đủ sức mạnh của Monolith, bao gồm xử lý transaction, debug dễ, deploy đơn giản.

Distributed Monolith - Cái bẫy nguy hiểm cần tránh

Trước khi kết thúc, phải nói thêm về một thảm họa mà nhiều hệ thống mắc phải, đó là Distributed Monolith. Nó là Monolith bị chia sai cách. Tức là bạn chia ra thành nhiều service nhưng các service lại phụ thuộc chặt chẽ vào nhau, muốn deploy phải deploy cùng lúc và gọi API qua lại loạn xạ. Kết quả là vừa phức tạp như Microservices, vừa không có lợi ích thật sự của nó.

Lời kết

Nếu bạn đang có ý định xây ứng dụng mà chưa biết nên chọn hướng nào, hãy bắt đầu bằng Modular Monolith. Làm chắc nền móng, rồi khi hệ thống đủ lớn, bạn hoàn toàn có thể chia nhỏ nó mà không cần đập đi xây lại.

Ở kỳ sau, chúng ta sẽ cùng nhau xây thử một Modular Monolith cơ bản với .NET, từ cách chia module, tổ chức thư mục, đến giao tiếp giữa các phần với nhau.

Bình luận

Gợi ý

0%