Chào mọi người, nếu như các bạn cũng biết thì dự án Teamcrop của mình xây dựng và chạy hoàn toàn trên kiến trúc Microservices và sau hơn 2 năm triển khai thì có một số vấn đề liên quan đến kiến trúc này, thiết nghĩ cần chia sẻ thêm với mọi người để mọi người thấy được rằng Microservices không phải là chìa khóa vạn năng như vẫn hay nghe quảng cáo, dụ dỗ. Mọi kiến trúc đều có đánh đổi và Microservices cũng vậy.
Mình sẽ viết một loạt bài (5, 6 bài gì đó) về việc tăng tốc cho kiến trúc Microservices mà đã rút tỉa được trong quá trình triển khai dự án Teamcrop, bởi tốc độ luôn là yếu tố hàng đầu khi xây dựng các ứng dụng web, và với kiến trúc mới này thì tăng tốc là một kỹ thuật cần xem xét khi triển khai.
Microservices là gì?
Microservices là các dịch vụ nhỏ, tách biệt đại diện cho 1 phần nhỏ tương ứng trong business domain của bạn. Với kiến trúc Monolithic, bạn sẽ có 1 server lớn chịu trách nhiệm giải quyết tất cả các requests. Việc này sẽ gây khó khăn rất nhiều trên phương diện scale. Microservices có thể cân bằng traffic theo nhu cầu của doanh nghiệp. Nếu đang nhận được 1 lượng lớn thanh toán, bạn có thể scale up thiết bị thanh toán và giữ các dịch vụ khác ở mức sử dụng 1 lượng nhỏ hơn các services.
Mô tả kiến trúc Microservices
Trong kiến trúc Microservices, các service (dự án) tồn tại độc lập nhau về xử lý (process), lưu trữ (database) và request (client/server model). Hình minh họa bên dưới là minh họa 1 thành phần trong kiến trúc microservices (lưu ý là nó không liên quan đến phần bài toán đề cập bên dưới).
Ví dụ bạn xây dựng một hệ thống bán hàng dựa trên Microservices (như Teamcrop chẳng hạn) thì giả sử một đơn hàng được mô tả với các thông tin sau “Hôm nay có nhân viên A tạo một đơn hàng B tại cửa hàng C và xuất từ kho D” thì bạn cần tối thiểu 4 service (project) với database độc lập:
- Employee service (sử dụng table tc_employee)
- Store service (sử dụng table tc_store)
- Inventory service (sử dụng table tc_warehouse)
- Order service (sử dụng table tc_order). Trong đó table tc_order chỉ chứa khóa ngoại – tức ID của Nhân viên, ID của cửa hàng, ID của nhà kho theo đúng tinh thần thiết kế chuẩn hóa database.
Bởi vì theo kiến trúc Microservices nên hệ thống bạn sẽ chạy 4 dịch vụ khác nhau như trên và chạy ở tối thiểu 4 instance (container, server) khác nhau.
Lợi ích của Microservices
Nếu đọc đến đây thì bạn sẽ thấy được việc tách ra như thế sẽ làm cho mô hình Microservices phát huy thế mạnh như đã quảng cáo là:
- Source code tinh gọn: bởi vì hệ thống cấu thành từ những dự án nhỏ, mỗi dự án sẽ đơn giản và tập trung vào 1 hoặc 1 vài nghiệp vụ chính nên code base và độ phức tạp cũng không cao. Giúp mang lại tính gọn nhẹ, dễ bảo trì và mở rộng.
- Bảo mật source code: vì nhân viên nào làm việc ở dự án nào thì chỉ truy cập được source code của dự án đó.
- Tồn tại độc lập: vì đây là 4 dự án khác nhau và có thể có cách deploy riêng, và một service nào đó chết thì service khác vẫn hoạt động bình thường.
- Scale độc lập: tùy theo nhu cầu sử dụng của hệ thống mà có thể scale riêng service đó, ví dụ như service đơn hàng sử dụng thường xuyên nên có thể chạy 2, 3 server (container) để tăng performance.
Tác dụng phụ của Microservices
Các điểm bên trên đúng là các ưu điểm của microservices, tuy nhiên, hãy nghĩ đến ngữ cảnh ở trên. Nếu ở website bạn hiện 1 table view với thông tin sau:
Invoice ID | Nhân viên | Cửa hàng | Kho xuất |
---|---|---|---|
123456 | Võ Duy Tuấn | Cropcom | Kho HCM |
thì bạn sẽ làm như thế nào và tối ưu nhất? Có thể trong đầu các bạn đã nghĩ đến JOIN, nhưng xin thưa, đây không phải là ứng dụng Monolithic, mà đây là microservice và 4 database table này ở 4 database server khác nhau nên không có chuyện JOIN gì cả, và ở table đơn hàng (tc_order) bạn chỉ có EmployeeID, StoreID và WarehouseID.
Chào mừng đến với tác dụng phụ của Microservices.
Một số chiến lược cơ bản
Để giải quyết bài toán hiển thị ở trên, bạn chỉ có thể tiếp cận theo hướng lấy dữ liệu trực tiếp từ service liên quan. Từ EmployeeID, gọi sang service Employee, từ StoreID thì gọi sang service Store…để lấy các thông tin cần hiển thị. Việc này sẽ dẫn đến giao tiếp liên service (inter-service communication).
Trong kiến trúc Microservices, càng hạn chế gọi liên service càng tốt vì các service sinh ra để phục vụ bên ngoài chứ không phải để phục vụ liên service, dẫn đến performance hệ thống sẽ bị giảm, vì nếu thiết kế không tốt, các service bị die hầu như do các service gọi lẫn nhau gây quá tải chứ từ client chưa chắc quá tải :).
Ngoài ra, gọi liên service sẽ có overhead vì vẫn có giao thức kết nối đi kèm (như HTTPS, Protobuf..) nên phải hạn chế. Do đó, cách dễ dàng tiếp cận nhất là sử dụng cache để không phải request nhiều đến các service mà chỉ cần mò vào cache. Có thể sử dụng Redis hoặc memcache cho tính năng này. Nhiệm vụ còn lại của bạn chỉ là làm sao clear cache một cách hiệu quả mà thôi.
Như vậy, với 1 đơn hàng, bạn sẽ cần thêm 3 request đến cache để fetch thêm thông tin (employee, store và warehouse) trước khi trả về client để hiển thị đầy đủ thông tin.
Tham khảo thêm: Việc làm Microservices lương cao tại Topdev
Teamcrop đã làm thế nào?
Ở trên là cách mình đề xuất và mọi người cũng nghĩ ra dễ dàng vì nó khá cơ bản cho các ứng dụng web hiện đại. Tuy nhiên, dự án Teamcrop không theo cách này và theo 1 cách “phức tạp” hơn nhiều và tất nhiên nó sẽ nhanh hơn cách ở trên.
Trong bài tiếp theo, mình sẽ chia sẻ chi tiết cách Teamcrop đã giải quyết bài toán này như thế nào, tận dụng web socket, service worker của trình duyệt để tăng tốc tối đa cho việc hiển thị dạng này.
Hy vọng bạn sẽ thích các thông tin này và sẽ tiếp tục theo dõi loạt bài chia sẻ kỹ thuật tăng tốc cho kiến trúc Microservices.
P.S: Teamcrop.com là hệ thống ERP dành cho chuỗi bản lẻ và luôn tìm kiếm lập trình viên PHP, nếu bạn biết PHP, yêu thích xây dựng các dự án web lớn, phức tạp trên những kiến trúc mới như Microservices, công nghệ mới như Docker thì đừng ngần ngại liên hệ với Tuấn (qua email tuanmaster2012@gmail.com) để tham gia cùng mình xây dựng những sản phẩm thú vị.
Có thể bạn quan tâm:
Nguồn: Bloghoctap
Devops đang rất quý, nhiều công ty hàng đầu cần tuyển Devops lương lên đến $3000