Kiến trúc Microservices đang thu hút sự quan tâm lớn từ cộng đồng phát triển phần mềm. Mặc dù có nhiều tài liệu giới thiệu về các lợi ích của nó, nhưng không phải ai cũng hiểu rõ và có cái nhìn chính xác về kiến trúc này. Bài viết này sẽ cung cấp một cái nhìn khách quan về ưu và nhược điểm của Microservices, giúp bạn đưa ra quyết định phù hợp cho dự án của mình. Trước khi đi sâu vào chi tiết, hãy cùng tìm hiểu lý do tại sao bạn nên cân nhắc sử dụng Microservices.
Mục Lục
Kiến trúc Monolithic (Nguyên Khối)
Để hiểu rõ hơn về Microservices, chúng ta hãy bắt đầu với kiến trúc Monolithic. Một ví dụ điển hình là ứng dụng gọi xe taxi qua điện thoại.
Kiến trúc Monolithic
Trong kiến trúc này, business logic được thể hiện qua các khối dịch vụ, đối tượng nghiệp vụ và các sự kiện (ví dụ: khách đặt xe, khách hủy xe). Xung quanh lõi là các adapter kết nối với cơ sở dữ liệu, hệ thống messaging, web service hoặc giao diện người dùng.
Mặc dù có cấu trúc module hóa hợp lý, ứng dụng Monolithic được đóng gói và triển khai thành một khối duy nhất. Mã chạy phụ thuộc vào ngôn ngữ lập trình và framework sử dụng.
Ứng dụng Monolithic phức tạp
Theo thời gian, các ứng dụng Monolithic trở nên lớn và phức tạp do việc bổ sung liên tục các tính năng mới. Điều này dẫn đến những hạn chế sau:
- Khó bảo trì và nâng cấp: Ứng dụng Monolithic phức tạp gây khó khăn cho việc bảo trì, nâng cấp và thêm tính năng mới.
- Khó áp dụng Agile: Khó triển khai các phương pháp phát triển Agile do tính liên kết cao giữa các thành phần.
- Triển khai lại toàn bộ hệ thống: Việc cập nhật hoặc nâng cấp một phần nhỏ của ứng dụng đòi hỏi phải triển khai lại toàn bộ hệ thống.
- Khó mở rộng: Việc mở rộng quy mô ứng dụng gặp khó khăn nếu các service có yêu cầu tài nguyên khác nhau (ví dụ: một service cần thêm CPU, service khác cần nhiều bộ nhớ).
- Độ tin cậy thấp: Một service không ổn định có thể làm sập toàn bộ hệ thống.
- Khó đổi mới công nghệ: Ứng dụng Monolithic thường sử dụng chung một công nghệ, gây khó khăn cho việc thay đổi hoặc áp dụng công nghệ mới.
Những hạn chế này đã thúc đẩy sự phát triển của kiến trúc Microservices.
Kiến trúc Microservices (Dịch Vụ Nhỏ)
Kiến trúc Microservices xây dựng ứng dụng như một tập hợp các dịch vụ nhỏ, độc lập, có thể chạy, phát triển và triển khai riêng biệt. Mục tiêu là giải quyết các vấn đề của kiến trúc Monolithic bằng cách chia nhỏ ứng dụng lớn thành các dịch vụ nhỏ, kết nối với nhau. Mỗi dịch vụ nhỏ thực hiện một tập các chức năng chuyên biệt, như quản lý đơn hàng hoặc quản lý khách hàng.
Mỗi dịch vụ là một ứng dụng nhỏ với kiến trúc đa diện, lõi là business logic kết nối với các adapter khác nhau. Một số dịch vụ cung cấp API cho các dịch vụ khác hoặc ứng dụng client. Mỗi dịch vụ nhỏ được chạy trong một máy ảo hoặc Docker container.
Kiến trúc Microservices
Trong kiến trúc Microservices, mỗi vùng chức năng được thực hiện bởi một dịch vụ nhỏ. Ứng dụng web cũng có thể được chia nhỏ cho từng đối tượng người dùng (ví dụ: hành khách/tài xế) để tối ưu hóa trải nghiệm, tăng tốc độ và dễ dàng tương thích.
Điều quan trọng là xác định các yêu cầu và khả năng cần thiết để đáp ứng một nghiệp vụ cụ thể trong ứng dụng Monolithic. Sau đó, mỗi nghiệp vụ sẽ được xây dựng thành các service nhỏ, độc lập, sử dụng các nền tảng công nghệ khác nhau và phục vụ một mục đích cụ thể.
Ưu điểm và Nhược điểm của Microservices
1. Ưu điểm
- Dễ dàng Continuous Delivery và Deployment:
- Cải thiện khả năng bảo trì: Mỗi service tương đối nhỏ, dễ hiểu và thay đổi.
- Khả năng testing dễ dàng hơn: Các service nhỏ hơn và nhanh hơn để kiểm tra.
- Khả năng triển khai tốt hơn: Các service có thể được triển khai độc lập.
- Phát triển độc lập: Các team khác nhau có thể phát triển, thử nghiệm, triển khai và mở rộng quy mô dịch vụ của mình một cách độc lập.
- Giảm thiểu rủi ro: Lỗi trong một service chỉ ảnh hưởng đến service đó, các service khác vẫn tiếp tục hoạt động. Trong kiến trúc Monolithic, một thành phần lỗi có thể ảnh hưởng toàn bộ hệ thống.
- Dễ dàng thay đổi công nghệ: Bạn có thể lựa chọn nhiều công nghệ mới khi triển khai các service. Khi có thay đổi lớn đối với các service hiện có, bạn có thể dễ dàng thay đổi công nghệ.
2. Nhược điểm
- Phức tạp trong việc tạo ra hệ thống phân tán:
- Giao tiếp giữa các services: Cần triển khai việc giao tiếp giữa các service (inter-services communication).
- Xử lý lỗi một phần: Xử lý lỗi một phần (partial failure) rất phức tạp vì một luồng xử lý cần đi qua nhiều service.
- Quản lý request: Thực hiện các request trải rộng trên nhiều service khó khăn hơn, đòi hỏi sự phối hợp cẩn thận giữa các team.
- Toàn vẹn dữ liệu: Khó khăn trong việc đảm bảo toàn vẹn cơ sở dữ liệu nếu triển khai theo kiến trúc cơ sở dữ liệu phân vùng.
- Triển khai và quản lý phức tạp: Triển khai và quản lý Microservices thủ công phức tạp hơn nhiều so với ứng dụng Monolithic.
- Xử lý sự cố: Cần xử lý các sự cố khi kết nối chậm, lỗi khi thông điệp không gửi được hoặc thông điệp gửi đến nhiều đích đến vào các thời điểm khác nhau.
Những Điều Cần Lưu Ý Khi Thiết Kế Microservices
1. Một Số Cách Hiểu Sai Về Microservices
- Số dòng code/ kích cỡ của đội lập trình không phải là chỉ số quan trọng: Không nên đánh giá kích thước của một service dựa trên số lượng dòng code hoặc kích thước của đội phát triển.
- “Micro” không có nghĩa là tạo ra các service nhỏ nhất có thể: Việc tạo ra các service quá nhỏ có thể vi phạm các nguyên tắc trong kiến trúc Microservices.
- Microservices không phải là SOA: Chỉ phát triển các service kiểu SOA rồi dán nhãn Microservices là hoàn toàn sai lầm và không mang lại bất kì lợi ích nào.
2. Cần Tuân Thủ Điều Gì?
- Single Responsibility Principle (SRP): Một service với phạm vi và chức năng giới hạn, tập trung vào một nhiệm vụ giúp quá trình phát triển và triển khai dịch vụ nhanh chóng hơn.
- Xác định và giới hạn các service theo chức năng nghiệp vụ thực tế.
- Đảm bảo Microservices có thể phát triển và triển khai độc lập.
- Phạm vi của Microservices phục vụ một nghiệp vụ, không chỉ đơn giản làm các dịch vụ nhỏ hơn. Kích thước hợp lý của một service là kích thước đủ để đáp ứng yêu cầu của một chức năng trong hệ thống.
- Microservice không nên có quá nhiều hàm hay chức năng hỗ trợ xung quanh và định dạng thông báo/ gửi tin (messaging) đơn giản.
Làm Thế Nào Để Duy Trì Tính Nhất Quán Dữ Liệu?
Để đảm bảo tính độc lập, mỗi service thường có một cơ sở dữ liệu riêng. Việc duy trì tính nhất quán dữ liệu giữa các service là một thách thức. Thay vì sử dụng 2 phase-commit/distributed transactions, ứng dụng nên sử dụng Saga pattern.
Saga Pattern
Một service publish một event khi dữ liệu của nó thay đổi. Các service khác consume event đó và cập nhật dữ liệu của chúng. Nếu một transaction thất bại, saga sẽ thực hiện một loạt các transaction để hoàn tác các transaction trước đó.
Khi Nào Nên Sử Dụng Kiến Trúc Microservices?
Một thách thức lớn là xác định thời điểm phù hợp để sử dụng kiến trúc Microservices. Khi phát triển phiên bản đầu tiên của ứng dụng, bạn thường không gặp phải các vấn đề mà Microservices giải quyết. Hơn nữa, việc sử dụng một kiến trúc phân tán phức tạp có thể làm chậm quá trình phát triển.
Do đó, trừ khi bạn có một hệ thống quá phức tạp để quản lý bằng kiến trúc Monolithic hoặc bạn dự đoán rằng ứng dụng sẽ trở nên phức tạp trong tương lai, thì kiến trúc Monolithic vẫn là một lựa chọn tốt.
