Nếu bạn đang sắp sử dụng Microservices, tôi có vài lời khuyên hữu ích có được từ kinh nghiệm chuyển đổi từ Monolith sang kiến trúc Microservice có thể scale & maintain được.
Background
Chúng tôi đã xây dựng platform này hơn 18 tháng. Mọi thứ bắt đầu rất đơn giản, chúng tôi có server (sử dụng Gin) với 1 số các REST endpoints như thế này:
https://oursite.com/api/v1/places https://oursite.com/api/v1/users https://oursite.com/api/v1/bookings
Mỗi resource đều có URL theo version riêng, mỗi cái hỗ trợ POST, GET, PATCH, DELETE khi cần thiết. Chúng tôi có 2 clients mobile riêng biệt, kết nối với các APIs này và database centralized. Chúng tôi đã dùng JWT để xác thực người dùng. Chúng tôi giải quyết 1 số lượng kha khá các request mỗi giờ. Mọi thứ có vẻ tốt, nhưng chúng tôi cần phải thay đổi platform. Các ứng dụng mobile đã không hoạt động.
Đây cũng là lúc vấn đề xảy ra. Chúng tôi có 1 lượng lớn các requirements mới liên quan đến 2 web app. Có 2 sự lựa chọn và chỉ 1 trong 2 là khả thi. Chúng tôi có thể vừa rewrite toàn bộ kiến trúc và dành nhiều tháng trời để viết 1 server mới với chức năng theo yêu cầu – hoặc có thể sử dụng server hiện tại và thêm chức năng mới vào. Vì thời gian gấp rút, chúng tôi đã dùng server hiện tại.
Sau vài tuần, các đoạn code kế thừa đã bắt đầu nhiều lên và chúng tôi lại gặp phải vấn đề. Việc thay đổi các models gặp khó khăn, khiến mọi thứ chỉ là chuyện vặt vãnh. Chúng tôi không thể kéo dài chuyện này và cuối cùng cũng đến bước ngoặt. Lựa chọn bây giờ là: hoặc tiếp tục build server hiện tại và gặp các vấn đề khó khăn liên quan đến scaling; hoặc tích hợp lên 1 cách tiếp cận mới scale được và cũng maintain được.
Vậy 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.
Có nhiều ý kiến khác nhau về cách thức hoạt động & trao đổi của 1 Microservice. Nếu nói Microservice đơn giản thì là bạn đang đánh giá quá thấp Microservices. Concept của kiến trúc Microservice đơn giản & khá lý tưởng. Còn việc thực thi ban đầu thì sao?
Biểu đồ ở trên giải thích sự khác biệt giữa kiến trúc Monolithic và kiến trúc Microservice rất rất đơn giả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. Tuy nhiên, 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. Đây được gọi là scaling theo chiều ngang.
Microservices có vẻ tuyệt đấy, nhưng tại sao lại khó?
Microservices là kiến trúc lý tưởng nên rất nhiều công ty thường thuyết giảng những lợi ích của Microservices, có thể kể đến như Uber, Google, AirBnb, Square… cùng rất nhiều công ty khác đã thực thi microservices tốt nhờ sở hữu resources và có thời gian để đàu tư vào việc xây dựng kiến trúc này.
Khi bắt đầu nghiên cứu Microservices, bạn sẽ nhanh chóng nhận ra cần phải quản lý tất cả những Microservices này và cân bằng tải trong khi giám sát tất cả mọi thứ đang diễn ra. Đừng quên rằng bạn cần phải test mỗi thiết bị trong local khi đang build các tính năng mới.
Sau vài tuần research & testing, đây là list nhỏ các nhiệm vụ cho mỗi services và các công cụ mà tôi khuyến khích bạn research
- Containers (Docker)
- Orchestration (Kubernetes)
- Management (Forge)
- Api Gateway / Canary (Ambassador)
- Edge Proxy (Envoy)
- Monitoring (Prometheus)
- Local Testing (Telepresence)
Bạn không nên nhồi nhét danh sách trên cho 1 service đơn giản. Tuy nhiên, có thể giám sát được các tương tác giữa các services và tổ chức chúng đòi hỏi phải thật mạnh mẽ. Có 1 số thuật ngữ có thể gây hiểu lầm, nên tôi sẽ giải quyết những từ gây hiểu lầm nhất.
Edge Proxy — Là quy trình chạy dọc service của bạn và proxy các traffic của các services thông qua hệ thống nội bộ riêng và thường sử dụng vài loại middleware (như prometheus) để giám sát và track traffic này. Ambassador được xây dựng trên Envoy và cung cấp nhiều tính năng hơn.
Containers — Bạn ắt hẳn đã nghe khá nhiều về Docker. Đây là chuẩn mực container trên web. Đây là cách chơi chữ dựa trên nghĩa của từ container. Bạn có thể nghĩ đến các docker containers và các shipping containers nhỏ chạy ứng dụng trên cloud với 1 orchestrator di chuyển chúng xung quanh và tối ưu hóa chúng. Containers cũng trực tiếp sử dụng linux containers.
Orchestration — Kubernetes là orchestrator nổi tiếng nhất, phối hợp rất tốt với Docker. Orchestration sẽ lấy docker container của bạn và chăm sóc chúng, đảm bảo rằng docker container sẽ hoạt động tốt.
Tôi nghe nói có thể sử dụng ngôn ngữ bất kì cho mỗi micro service, đúng không nhỉ?
Chắc chắn rồi. Tuy nhiên, điều đó không đồng nghĩa là hiệu quả như nhau, và có thể sẽ tốn thời gian của bạn nữa. Giải pháp là tạo 1 kiến trúc Microservice ổn định, scale được để đảm bảo là kiến trúc có thể maintain và đi theo được luồng chung trong doanh nghiệp của bạn.
Kiến trúc của bạn nên có các foundations vững chắc. Nếu ai đó phải làm việc với dự án của bạn, bạn nên nói với người đó như thế này:
Nhìn chung, các services được viết bằng {ngôn ngữ chính}. Chúng sử dụng các frameworks sau: {danh sách tên các frameworks}. Nếu bạn nghĩ mỗi service sử dụng 1 ngôn ngữ khác, bạn phải đảm bảo rằng nó có cùng chức năng như các services hiện tại.
Việc sử dụng cùng 1 ngôn ngữ trong các dự án của bạn sẽ đảm bảo tính nhất quán trong các dự án của bạn. Tất nhiên là vẫn sẽ có ngoại lệ. Nếu có 1 service thực hiện các bài toán phức tạp và đang xử lý rất nhiều traffic, bạn sẽ muốn chọn 1 ngôn ngữ phù hợp hơn để xử lý task đó. Và đó sẽ không phải là 1 task đơn giản. Nếu bạn có các dependencies trong PSL (primary service language), thì nên đầu tư thời gian để rebuild bằng ngôn ngữ mới.
Các microservices trao đổi với nhau như thế nào?
Một trong những vấn đề chính của Microservices trong quá khư là các vấn đề về độ trễ. Tạo 1 lượng lớn các HTTPS requests giữa 1 số lượng các services có thể gây ra mức độ trễ đáng kể đối với client. Đây là cách tiếp cận không khả năng và chắc chắn sẽ không gọn nhẹ như mong muốn.
Một cách tiếp cận mới cho Microservices đó là gRPC. gRPC là 1 framework RPC mang lại hiệu quả cao. Dữ liệu nhị phân được gửi qua wire ở tốc độ cao, đi cùng quá trình serialisation/ deserialization nhanh.
Bằng cách sử dụng gRPC, bạn sẽ xác định các models bằng định nghĩa protobuf, khá đơn giản và các models này có 1 protobuf compiler cho nhiều ngôn ngữ thông dụng. Sử dụng gRPC sẽ giảm bớt nỗi lo của bạn về độ trễ.
Tuy nhiên, sử dụng các protobuf models sẽ gây ra vài nhầm lẫn. Versioning. Chúng tôi đã nghiên cứu vấn đề này trong vài tuần qua, tự hỏi làm sao rất nhiều services khác nhau có thể chia sẻ cùng protobuf models (như 1 user model chẳng hạn). Chúng ta cũng nghĩ đến những ý tưởng liên quan đến việc giữ các protobuf models trong versioned git repository nhưng lại thấy không thuyết phục. Chúng tôi hiện đang đầu tư cơ chế tốt nhất cho việc này.
Ngoài ra cũng có những vấn đề phát sinh khi sử dụng gRPC. Bạn có thể phải maintain 1 REST API chuẩn cho các web clients chuẩn mực thì mới access được. Chúng tôi sử dụng envoy và grpc-gateway và đã có những bước tiến nhất định. Tuy nhiên, đây vẫn là vấn đề phức tạp và dường như không dễ giải quyết được trong thế giới Microservice.
Migrating
Nếu bạn đang định bắt đầu bằng việc xây dựng 1 kiến trúc Microservice thì tôi khuyến khích là không nên. Bạn sẽ dành rất nhiều thời gian thực hiện các hoạt động tối ưu trước đó cho các domains mà bạn không thực sự biết là nó có tồn tại. Để tạo 1 kiến trúc Microservice vững chắc, bạn sẽ cần biết chính xác lý do tại sao mình phải làm như vậy.
Tuy nhiên, nếu bạn đã có 1 kiến trúc Monolith và có ý định chuyển đổi thì đây là vài lời khuyên:
- Xác định rõ business domains của mình (bounded contexts)
- Tìm hiểu kĩ về Docker, Kubernetes và Envoy
- Tìm hiểu về các công cụ monitoring và testing
- Dành thời gian để demo
Đó là trải nghiệm riêng của chúng tôi. Chúng tôi đã dành rất nhiều thời gian trên Google Cloud Platform để tạo các kiến trúc khác nhau với các công cụ mới, nhằm phát hiện được cái nào là tốt nhất. Hiện chúng tôi đang sử dụng stack sau:
Primary Service Language: Go Primary Service Datastore: Postgresq Cloud Platform: Google Cloud Containers: Docker Container Orchestration: Kubernetes Edge Proxy: Envoy Local Testing: Telepresence Monitoring: Prometheus Management: Forge
Đã vài tháng trôi qua kể từ khi chúng tôi hoàn thiện quá trình chuyển đổi. Mọi thứ đã rất khó khăn, nhưng gần đây, chúng tôi đã gặp được 1 công ty có thể phá vỡ mọi rào cản phức tạp khi bắt đầu quá trình xây dựng kiến trúc Microservices. Họ đã tạo ra 1 số công cụ hỗ trợ khá tốt mà bạn có thể tham khảo tại https://www.datawire.io.
Nguồn: TopDev via hackernoon.com