Cá nhân tôi nghĩ, cloud-native là một khái niệm khó cả về ngữ nghĩa và cách thực thi trong thực tế. Định nghĩa cloud native đã xuất hiện quá nhiều trên internet, tôi không muốn nhắc lại. Trong bài viết này, chúng ta hãy cùng nhau ngồi lại và thảo luận một số những luận điểm mà tôi nghĩ rằng rất nhiều người trong chúng ta đã và đang làm cloud-native còn chưa thực sự tường minh. Luận điểm đầu tiên tôi muốn raise lên đó chính là: Cloud Native liệu có cần microservice hay không?
Dạo qua một vòng tất cả các bài viết, nghiên cứu về cloud native, ta dễ dàng nhận thấy rằng microservices là một phần không thể thiếu trong cloud native. Vấn đề này được đề cập nhiều đến mức nó trở thành một tiêu chuẩn trong tiềm thức của những người phát triển phần mềm theo hướng cloud native, tạo ra một cảm giác như ta không có sự lựa chọn nào khác ngoài microservices. Vậy thực sự có cần thiết hay bắt buộc phải có microservice hay không?
Một câu hỏi đặt ra là nếu cho các bạn viết một ứng dụng từ thời điểm ban đầu a.k.a from scratch thì các bạn sẽ sử dụng ngay microservice hay monolith? Rất nhiều chiến lược mà các đơn vị phát triển phần mềm đưa ra là phải đi theo microservice, nhưng đi theo như thế nào thì không phải dễ dàng để trả lời câu hỏi đó. Có một số nghiên cứu, lý luận dựa trên thực tiễn chỉ ra rằng, với các ứng dụng được phát triển từ con số 0 đi lên (greenfield) thì trước khi tiến đến microservice, hãy bắt đầu bằng monolith trước. Microservice chỉ nên được áp dụng khi các ứng dụng monolith phình to với nhu cầu người dùng tăng cao. Cá nhân tôi cho rằng, hãy chỉ nên cân nhắc sử dụng microservice trong các trường hợp sau:
- Team size phải đủ lớn.
- Các thành phần cấu thành trong phần mềm được lên kế hoạch là sẽ được release và triển khai một cách độc lập.
- Domain model rõ ràng và có thể được phân chia dễ dàng, rành mạch.
- Sẵn sàng chấp nhận sự phức tạp của mô hình microservice, xa hơn sẽ là servicemesh.
Một trong những vấn đề thực tế mà cá nhân tôi hay gặp đó là: Rất nhiều team đã và đang đóng gói mã nguồn của họ vào trong container, sau đó sử dụng các giải pháp container orchestrator như K8S để deploy cũng như quản trị các container đó, thậm chí họ áp dụng rất nhiều các mô hình về kiến trúc microservice. Thêm vào đó, họ cũng build các giải pháp CI/CD với rất nhiều tính năng mới, và họ cũng chạy các giải pháp CI/CD đó trên nền tảng container. Tổng hoà các yếu tố trên họ cho rằng họ đang ứng dụng kiến trúc microservice cho quá trình phát triển phần mềm của họ. Tuy nhiên, điều này không thực sự đúng. Dưới đây là một khảo sát trong việc mục đích sử dụng container của Red Hat:
Khá là thú vị khi con số cao nhất về lý do dùng container đó là phục vụ cho phát triển nghề nghiệp chứ không liên quan gì đến kiến trúc phần mềm hay bất cứ một lý do gì liên quan đến microservice hay cloud native. Khái niệm này còn được nhắc đến với một mỹ từ: CV-driven development. Hãy tưởng tượng trong CV xin việc của các bạn có những dòng liên quan đến kinh nghiệm sử dụng container trong phát triển phần mềm, điều đó hoàn toàn có lợi cho các bạn, còn việc lợi ích sử dụng nó như thế nào, có liên quan đến microservice hay không, hãy thử phản biện một chút:
- Các microservices cần phải được release và deploy một cách độc lập, không ảnh hưởng lẫn nhau. Điều này không chỉ đơn thuần là các microservice độc lập về việc triển khai, vận hành mà còn độc lập trong việc thực thi các tác vụ business. Tức là nếu ta deploy/rollback bất cứ version nào của 1 microsevice, nó không ảnh hưởng đến hoạt động của các microservice còn lại. Container và container orchestration không giải quyết được vấn đề này. Nó chỉ vô hình chung tạo ra các distributed monolith mà mỗi monolith đã được biến tấu để tạo cảm giác “microservice” bằng cách chúng được phát triển trên các git repo khác nhau.
- Đóng gói và sử dụng các container với các container orchestration cũng không giải quyết được vấn đề liên quan đến coupling giữa các service. De-coupling các service dựa trên các domain được phân tách rõ ràng là tiền đề cho sự độc lập, không phụ thuộc lẫn nhau. Decoupling dễ dàng nhận thấy được bằng việc quan sát rằng: nếu 1 microservice breaks mà các microservice không break, vẫn hoạt động bình thường thì đó chính là biểu hiện của decoupling.
- Distributed != Decouping: Hệ thống phân tán giúp ta giải quyết được rất nhiều bài toán nhưng nó cũng để lại rất nhiều vấn đề. Nếu ta nghĩ rằng, việc thực hiện decoupling bằng cách deploy các service theo hình thức phân tán trên các server khác nhau thì không những không giải quyết được bài toán decoupling mà còn gặp phải những vấn đề liên quan đến phân tán. Như tôi đã trình bày ở trên, decoupling không phải là các service được triển khai ở đâu, không phải khái niệm về vị trí mà đó là khái niệm của “tính độc lập”.
Vietstack/Tuti