Chuyển đổi từ monolith sang microservices qua ví dụ
1. Why microservices?
Microservices là kiến trúc hệ thống phần mềm hướng dịch vụ, chia nhỏ hệ thống ra thành các dịch vụ nhỏ, isolate về business và dữ liệu. Microservices đã trở nên phổ biến trong những năm trở lại đây, với những ưu điểm nổi bật, nó đang thay thế các ứng dụng monolith. Một số đặc trưng của microservices như sau.
- Triển khai độc lập
Nhờ chia nhỏ 1 ứng dụng lớn ra làm nhiều ứng dụng nhỏ hơn, hệ thống trở lên linh hoạt trong triển khai. Linh hoạt từ việc lựa chọn công nghệ cho đến phân phối tài nguyên. Hệ thống có thể đạt được tiêu chí scalability, high availability.
- Giảm sự phụ thuộc
Các module được xác định rõ trách nhiệm, việc ràng buộc trong sử dụng chung code business, model và database được giảm xuống.
- Định hướng xoay quanh nghiệp vụ
Microservices hướng đến các dịch vụ xoay quanh business, một service là một ứng dụng có thể chạy độc lập. Development teams thường sẽ chỉ phải tập trung vào phát triển business.
- Khả năng phát triển, bảo trì và kiểm thử
Các stack khác nhau có thể được áp dụng chung trong giải pháp tổng thể, thậm chí tái sử dụng từ một hệ thống khác mà không phải lo về sự tương thích. Việc kiểm thử cũng dễ triển khai hơn với các dịch vụ nhỏ, các nghiệp vụ rõ ràng. Trong bài viết này mình sẽ không đi sâu để so sánh giữa monolith và microservices, xem thêm tại => Monolith vs. microservices.
2. The Microservices Layer?
Nếu chúng ta đã quen làm việc với monolith, từ việc code tất cả trên cùng một repo, một máy chủ dedicated về cấu hình, một database phục vụ tất cả các mục đích... thì việc chuyển đổi qua microservices thực sự là một thử thách. Ở vị trí của người thiết kế hệ thống, có quá nhiều thứ mới để hiểu và áp dụng để có thể có được best P/P (price/performance) mà vẫn có khả năng mở rộng. Một kiến trúc microservices hiệu quả là sự phối hợp một các hợp lý giữa các tech stack. Ta có thể chia microservices làm 4 layer:
2.1. Infastructure layer
Sự chuyển dịch từ traditional computing sang distributed computing/cloud computing tạo điều kiện rất thuận lợi cho việc áp dụng kiến trúc microservices. Việc triển khai microservices mà không có sự hỗ trợ từ hạ tầng sẽ tốn nhiều công sức hơn đáng kể. Ở dưới cùng là hạ tầng với các thành phần cơ bản:
- Servers
- Host level loging/monitoring
- Operating systems
- Resource isolation
- Configuration management
2.2. Communication layer
Layer này dễ gây nhầm lẫn, bởi vì nó chạm đến tất cả các layer khác trong hệ sinh thái. Nó bao gồm tất cả mọi thứ liên quan đến giao tiếp giữa ứng dụng, hệ thống và dịch vụ bao gồm:
- DNS
- Endpoint
- Load balancing
- Messaging
- Network
- Service registry
- Service discovery
2.3. The Application platform
Layer thứ 3 là nơi chứa tất cả các công cụ nội bộ, hệ thống, dịch vụ mà các microservices chạy trên đó. Một application platform tốt là nơi các công cụ được centralize về mặt quản lý, system-wide về mặt phạm vi. Development teams chỉ cần quan tâm đến các microservices mà họ làm việc, không phải những thứ stuff phía dưới. Layer này bao gồm:
- Deployment management (tools and pipeline)
- Development environment
- Application-level logging and monitoring
- Test, package, build and release tools
2.4. The Microservices Layer
Các developer tập trung tại layer này và tập trung vào business. Layer này nên độc lập với các layer phía dưới. Nó chỉ chứa các microservices và các cấu hình giữa chúng.
- Microservices
- Microservices configuration
3. Transform the Monolith to microservices in action
Cùng xem xét một ứng dụng monolith truyền thống với các tier Presentation, Business logic và Data access layer.
3.1. Business and Tech Stacks
Các đặc trưng của hệ thống hiện tại
Business: Ứng dụng thương mại điện tử.
Architect: 3 Tiers Application bao gồm Presentation, Business logic, Data access layer sử dụng Spring MVC, Spring Data
Database: Database sử dụng Mysql
Hosting: Ứng dụng được triển khai bằng file jar và database trên server đặt tại công ty
3.2. Các issue hệ thống đang gặp phải
- Spring MVC dựa trên kiến trúc server side rendering, multiple pages application, dẫn đến việc load trang lâu hơn
- Hệ thống downtime mỗi khi nâng cấp phiên bản mới, cho dù là tính năng nhỏ nhất của một module
- Hiện tượng bottle neck xuất hiện mỗi khi có nhiều người cùng truy cập hoặc thực hiện các tác vụ nặng, lost các đơn hàng, hệ thống order không hoạt động ổn định, thậm chí down cả dịch vụ. Tăng cấu hình tài nguyên thì tốn kém khi hệ thống tải thấp, nhưng vẫn ko đủ phục vụ khi hệ thống tải cao.
- Chức năng tìm kiếm sản phẩm chậm do dùng query truyền thống
- Quản lý build number của app và data một cách thủ công, bằng cách backup các file vật lý (.jar, sql)
- Hệ thống trace log cũng thủ công bằng cách write ra file, khó để trace lại khi có error
- Hệ thống chứa nhiều module nghiệp vụ, code đang phức tạp và khó maintain, việc phát triển tính năng mới đòi hỏi phải test lại toàn bộ hệ thống
- Ảnh sản phẩm được lưu trữ trực tiếp trên một máy chủ khác, khó quản lý
3.3. Chuyển đổi hệ thống sang microservice
Chuyển đổi các business module sang microservices:
- Authentication
- Product management
- Warehouse
- Order/Payment
- Shipping
- Report
- Client site
- Cms site
Chuyển đổi về architect:
Như phân tích ở trên, vấn đề khó khắc phục nhất trong các issue là vấn đề ứng dụng chạy trên nền tảng dedicated resource (VM) dẫn đến không thể kịp thời scale theo lượng tài nguyên yêu cầu, ảnh hưởng trực tiếp đến chất lượng hệ thống và trải nghiệm người dùng. Xem xét các chuyển đổi về architect:
- Triển khai ứng dụng dựa trên container orchestration (K8S concept), phục vụ mục đích scalability, high availability
- Tối ưu tìm kiếm sản phẩm bằng việc dựng thêm elastic service, đồng bộ với Product database
- Xem xét nâng cấp database sang mô hình master-slave để tối ưu hiệu quả đọc ghi.
- Load balancer cân bằng tải cho các instance mỗi khi hệ thống cao tải
- API gateway giúp ẩn kiến trúc phía sau và authentication/ request logging tập trung
- Lựa chọn công nghệ message queue cho giao tiếp bất đồng bộ giữa microservices
- Client site và cms site sử dụng công nghệ client site rendering (angular/react) để đạt higher performance. Việc phát triển tầng UI và business logic được tách biệt
- Separate các database cho mỗi dịch vụ, tăng resource cho các database có nhiều request, thậm chí áp dụng DB replica, master/slave => tăng tính bảo mật và upgrade về sau
- Sử dụng docker hub hoặc private image registry để lưu trữ các bản build của service dưới dạng image tag.
- Áp dụng các công nghệ có thể backup data dưới dạng backup volume bên cạnh dạng backup file truyền thống
- Chọn một stack cho việc lưu trữ file (ảnh sản phẩm, Database backup): Object storage technology (Sun S3)
3.4. Lựa chọn tech stack, provider và triển khai
Với cùng một thiết kế hệ thống, chúng ta có thể điều chỉnh lựa chọn tech stack và provider phù hợp với hoàn cảnh của mỗi công ty. Trên thị trường quốc tế có các tên tuổi lớn về cloud provider và app platform nổi tiếng như AWS, GCP, Microsoft azure. Trong nước thì có các nhà cung cấp như VNG cloud, Viettel IDC, CMC, FPT, Sunteco Cloud với các mức giá và dịch vụ khác nhau. Mình sẽ triển khai hệ thống này trên Sunteco Cloud, lấy trọng tâm là Sun Spinner, đây là dịch vụ dựa trên concept của K8S, hỗ trợ sẵn Load balancing, HA và scability chỉ với vài click. Một Sun-spinner có thể chứa một hoặc nhiều container.
- Sau khi build các service sang dạng image và đẩy lên docker hub, setup các Sun Spinner cluster từ giao diện
- Sun Spinner cho phép run bất kì image nào trên docker hub hoặc các image registry khác, thao tác hoàn toàn qua UI
- Database có thể được triển khai qua 3 cách trên Sunteco Cloud,
-
- Tạo một mysql-spinner sau đó sử dụng persistance volume (Vùng nhớ lưu trữ lâu dài) và mount vào data stored path của mysql-spinner
-
- Cách truyền thống hơn là sử dụng dịch vụ Sun VM để host database với dedicated resource
-
- Dịch vụ Database as a service (Comming soon)
- Các service-config được setup qua hệ thống Secret/ Configmap và mount trực tiếp vào Spinner. Đơn giản hóa quá trình quản lý configuration
- Các trang static web (landing page) có thể host trên Sun VM hoặc Sun S3 storage
- Message queue sử dụng Sun Highway (kafka as a service) Vòng đời của các service: CICD => push to docker hub => Sun Spinner pull image => Service booting => Service running. Có một góp ý nhỏ là Spinner chưa có cơ chế tích hợp với hệ thống CICD của các doanh nghiệp, có lẽ cần một api callback để trigger việc cập nhật ứng dụng lên phiên bản mới. Hiện tại phải lên portal của Sunteco Cloud để manual update version mới hoặc setup Sun Spinner với auto update policy. Nhờ việc chỉ cần facing ứng dụng web và api gateway ra ngoài, các ứng dụng phía sau giao tiếp với nhau qua internal endpoint, message broker mà performance và security được nâng cao. Mình chưa đề cập đến vấn đề database relication, xin hẹn ở những bài viết sau.
4. Conclusion
Các bạn có thể cân nhắc chuyển đổi toàn bộ hoặc từng phần ứng dụng của doanh nghiệp với mức chi phí nhỏ nhất để đặt được hiệu quả tốt nhất. Công nghệ container cho phép ứng dụng có thể scale một các tùy ý. Sun Spinner của Sunteco có pricing theo giờ, có nghĩa là nếu hệ thống tải bình thường thì lượng tiêu thụ chỉ tương đương với VM cùng cấu hình, nhưng khi hệ thống tăng tải, cấu hình được tự động scale ngay lập tức để đáp ứng nhu cầu, khi hệ thống giảm tải, cấu hình lại trở về mức bình thường. Tất cả các nhu cầu này nếu tự dựng một hệ thống K8S rồi tự setup sẽ tốn khá nhiều nguồn lực và chưa chắc đã hoạt động ổn định. Việc chuyển đổi từ kiến trúc monolith sang microservices hoặc xây dựng mới hoàn toàn là không dễ dàng, nhưng nó rất đáng giá để thực hiện.
Reference https://www.susanjfowler.com/blog/2016/12/18/the-four-layers-of-microservice-architecture
All rights reserved