FOUNDATION - MICROSERVICES LÀ GÌ? (PART 2)
Mình sẽ tiếp tục phần tiếp theo của cuốn sách "Building Microservices: Designing Fine-Grained Systems". Ở phần trước, chúng ta đã đi sơ lược qua về Microservices và những khái niệm quan trọng của nó. Ở phần này, chúng ta sẽ tiếp tục "Chapter 1: What are Microservices?" tìm hiểu về Monolith - một kiến trúc phần mềm phổ biến - để hiểu được điểm mạnh, yếu của kiến trúc này.
Bắt đầu nhé!
------------------------------------------------
Cấu trúc nguyên khối - The Monolith
Tuy chủ đề của chúng ta là Microservices, nhưng đừng quên Microservices được chú ý bởi nó là phương án tiếp cận thay thế cho kiến trúc truyền thống - Monolith. Để có thể phân biệt rõ ràng cũng như giúp bạn thật sự hiểu giá trị của kiến trúc Microservices, chúng ta cũng nên thảo luận về Monolith.
Khi tôi (tác giả) nói về Monolith, tôi chủ yếu đề cấp đến một đơn vị của việc triển khai (deploy). Khi mà toàn bộ chức năng của hệ thống phải được triển khai cùng nhau, tôi xem nó là Monolith. Có nhiều kiến trúc sẽ phù hợp với định nghĩa này, tuy nhiên chúng ta sẽ đi sâu về 3 loại: Monolith đơn luồng, Monolith dạng mô-đun và Monolith phân tán.
Monolith đơn luồng (Single-Process)
Khi nhắc đến Monolith, điều đầu tiên nảy ra trong đầu chúng ta là một hệ thống với code được deploy với một luồng duy nhất, như Hình 1-6. Có thể sẽ có nhiều phiên bản của nó để có thể mở rộng tốt hơn hoặc bền vững hơn, nhưng về cơ bản tất cả code sẽ được đóng gói vào một luồng duy nhất. Trong thực tế, hệ thống đơn luồng kiểu này có thể xem là một loại hệ phân tán đơn giản theo một cách nào đó bởi vì chúng gần như luôn thực hiện việc đọc dữ liệu hoặc lưu dữ liệu vào CSDL, hoặc hiển thị thông tin lên giao diện ứng dụng.
Việc deploy một Monolith đơn luồng có thể phù hợp với nhiều tổ chức. Nhà sáng lập của Ruby on Rails - David Heinemeier Hansson - đã chứng minh rằng loại kiến trúc này phù hợp với những tổ chức nhỏ. Kể cả khi tổ chức đó phát triển, Monolith vẫn có tiềm năng phát triển cùng và trở thành "The modular Monolith".
Monolith dạng mô-đun - The Modular Monolith
Như một tập con của Monolith đơn luồng, Monolith dạng mô-đun là một loại biến thể trong đó luồng đơn sẽ bao gồm nhiều module riêng biệt. Mỗi module có thể làm việc độc lập nhưng vẫn cần kết hợp lại để triển khai cùng nhau, như Hình 1-7. Khái niệm về việc chia nhỏ phần mềm thành các module không có gì mới, phần mềm được module hóa có nguồn gốc từ việc lập trình có cấu trúc vào khoảng những năm 1970, thậm chí có thể là lâu hơn về trước nữa. Tuy nhiên, đây là một cách tiếp cận mà tôi chưa thấy nhiều tổ chức sử dụng một cách hợp lý.
Một trong những thách thức của Monolith dạng module chính là việc CSDL có xu hướng thiếu sự phân tách như trong code, dẫn đến trở ngại đáng kể nếu muốn tách hệ thống sau này. Tôi cũng đã thấy một số team thử nghiệm việc đưa kiến trúc Monolith dạng module này đi xa hơn bằng cách phân rã CSDL theo cùng với các module, như Hình 1-8.
Monolith phân tán - The Distributed Monolith
"A distributed system is one in which the failure of a computer you didn’t even know existed can render your own computer unusable" -- Leslie Lamport
Monolith phân tán là hệ thống bao gồm nhiều dịch vụ, nhưng cho dù với bất kỳ lý do nào, chúng bắt buộc phải triển khai cùng nhau. Hệ Monolith phân tán có thể đáp ứng định nghĩa với SOA (Service-Oriented Architecture, mình đã đề cập ở Part 1), nhưng nó lại không thực hiện được những điểm tốt hứa hẹn của SOA. Với kinh nghiệm của tôi, Monolith phân tán có tất cả điểm yếu của hệ thống phân tán, và cả điểm yếu của Monolith đơn luồng, mà không có đủ mặt tích cực của cả 2 hệ thống đó.
Distributed monoliths, hoặc "monolith phân tán", thường xuất hiện trong một môi trường mà không đủ tập trung vào các khái niệm như che giấu thông tin và sự liên kết của chức năng kinh doanh. Thay vào đó, kiến trúc có sự liên kết mạnh làm cho các thay đổi lan rộng qua các ranh giới dịch vụ và các thay đổi dường như vô hại, có vẻ chỉ ảnh hưởng cục bộ, thực tế lại phá vỡ các phần khác của hệ thống.
![](chrome-extension://bpggmmljdiliancllaapiggllnkbjocb/logo/48.png)
Bổ sung của người viết:
Để hiểu rõ hơn, hãy tưởng tượng rằng bạn có một ứng dụng phức tạp được xây dựng dưới dạng một Monolith, tức là một ứng dụng lớn và phức tạp được triển khai trên một môi trường phân tán, với nhiều phần mềm con chạy trên các máy chủ khác nhau.
Tuy nhiên, mặc dù hệ thống được phân tán thành nhiều phần, kiến trúc tổng thể vẫn có sự liên kết mạnh giữa các thành phần. Điều này có nghĩa là sự thay đổi trong một phần của hệ thống (ví dụ: một phần mềm con) có thể gây ra ảnh hưởng đến các phần khác của hệ thống. Điều này xảy ra do sự phụ thuộc mạnh mẽ giữa các thành phần, khiến cho việc thay đổi trong một thành phần nhất thiết phải được phản ánh và thay đổi trong các thành phần khác.
Monolith và vấn đề xung đột trong quá trình triển khai - Monoliths and Delivery Contention
Khi càng nhiều người làm việc tại cùng một khu vực, họ sẽ cùng gặp một vấn đề. Ví dụ như khi những lập trình viên (LTV) khác nhau muốn thay đổi cùng một đoạn code, hay những team khác nhau muốn đẩy tính năng mới lên tại những thời điểm khác nhau, và sự nhầm lẫn về việc ai sở hữu cái gì và ai đưa ra quyết định (Trích đoạn này đề cập đến sự nhầm lẫn về việc ai sở hữu và quản lý các phần của hệ thống, cũng như ai đưa ra quyết định trong quá trình triển khai phần mềm). Các nghiên cứu đã chỉ ra rằng khi không rõ ràng về sở hữu và quyền quyết định, sẽ luôn có những khó khăn và xung đột xảy ra. Tôi gọi vấn đề này là "xung đột trong quá trình triển khai".
Việc hệ thống thiết kế theo Monolith không có nghĩa là bạn luôn luôn sẽ đối mặt với thách thức của vấn đề này, trong khi đó nếu với hệ thống Microservices thì bạn sẽ không bao giờ gặp phải. Tuy nhiên, kiến trúc dạng Microservices cho phép bạn phân định những ranh giới cụ thể mà quyền sở hữu có thể được xác định rõ ràng trong hệ thống. Do đó, bạn cũng có thể linh hoạt hơn khi gặp vấn đề xung đột và giảm thiểu được các bất cập.
Lợi ích của Monolith - Advantages of Monoliths
Một vài cấu trúc dạng Monolith, như Monolith đơn luồng hay Monolith dạng module có hàng tá những lợi ích. Việc cấu trúc triển khai đơn giản hơn nhiều giúp chúng có thể tránh được nhiều lỗi tiềm năng liên quan đến hệ thống phân tán. Từ đó, quy trình làm việc, giám sát, khắc phục sự cố hay kiểm thử đầu cuối sẽ dễ dàng hơn đáng kể.
Monolith cũng có thể đơn giản hóa việc tái sử dụng code trong chính nó. Nếu bạn muốn tái sử dụng code với một hệ phân tán, bạn cần xem xét nơi muốn sao chép, tách thư viện hay đưa chức năng dùng chung vào cùng một dịch vụ. Với Monolith, lựa chọn vô cùng đơn giản, mọi thứ ở đó và sử dụng thôi.
Không may thay, mọi người đều nhìn Monolith như một thứ cần phải né tránh, một thứ gì có rất nhiều vấn đề. Có người còn xem rằng Monolith đồng nghĩa với "di sản". Đó là một vấn đề. Kiến trúc Monolith là một lựa chọn, một lựa chọn hoàn toàn hợp lệ. Với tôi (tác giả), chúng ta nên tìm lý do để sử dụng chúng (một kiến trúc), thay vì tìm lý do để không sử dụng chúng.
Nếu rơi vào tình huống mà chúng ta liên tục đánh giá thấp khả năng của kiến trúc Monolith, chúng ta có nguy cơ không đáp ứng đúng nhu cầu của người dùng phần mềm chúng ta đang phát triển.
Vì vậy, trước khi loại bỏ hoặc đánh giá thấp kiến trúc đơn khối, chúng ta cần xem xét kỹ lưỡng và đánh giá xem nó có thể đáp ứng được yêu cầu của dự án và mục tiêu kinh doanh, cũng như cân nhắc các lựa chọn kiến trúc khác. Điều quan trọng là đảm bảo rằng chúng ta đưa ra quyết định dựa trên sự hiểu biết chính xác về kiến trúc và tác động của nó đối với dự án và người dùng cuối.
--- NeO ---
![](chrome-extension://bpggmmljdiliancllaapiggllnkbjocb/logo/48.png)
Nhận xét
Đăng nhận xét