Bài viết này là tổng hợp từ nhiều nguồn và từ kinh nghiệm của bản thân khi triển khai hệ thống theo kiến trúc Microservices từ đầu và chuyển đổi từ Monolith sang Microservices.
Microservices là gì?
Microservices – hay còn được gọi là kiến trúc Microservices và kiến trúc này thường được sử dụng ở backend hay có hệ thống lớn. Monolith được hiểu là code nguyên cục rồi deploy lên server, còn nếu chia thành nhiều cục nhỏ, mỗi cục này đảm nhiệm một nghiệm vụ riêng biệt và tách biệt nhau, có cùng hoặc chung tech-stack thì được gọi là Microservices.
Vậy, lợi ích của việc chuyển đổi Microservices? Bản thân mình cũng gặp các câu chuyện quen thuộc như sau:
- Team muốn deploy một tính năng mới, nhưng có các tính năng khác đang bị lỗi cần sửa gấp/ hoặc đang test, phải đợi mọi thứ xong hết mới có thể deploy tính năng mới này được. Sẽ có cách giải quyết là dùng source cotrol (git/tfs/svn), nhưng nó vẫn phải là deploy lại toàn bộ code, và dịch vụ phải tắt để chờ deploy.
- Mọi team member đều thấy được full code/ hoặc ác hơn là đối tác sẽ thấy được full code nếu như cùng với đội dev trong nhà phát triển, lúc này mình muốn bảo mật các nghiệm vụ hay giới hạn thfi khó khăn vô cùng.
- Cục source dùng stack quá cũ/ nặng nề/ hay đơn giản là mất source code, còn mỗi binary, hay đơn giản là muốn apply 1 framework mới vào, thì chắc chắn không ai dám đập ra làm lại từ đầu.
- Khó khăn khi training người mới để có thể handle được và follow strictly theo stack/ convention từ thuở ban đầu, hoặc techlead tạo ra source đã bay màu thì thôi nát luôn.
- …
Các sai lầm phổ biến về Microservices
Và Microservices sẽ giải quyết hết các vấn đề phát sinh ở trên. Tuy nhiên, việc chuyển đổi hệ thống sang Microservices không giúp làm hệ thống chạy nhanh hơn. Đôi khi việc dịch chuyển này lại phải quay đầu là bờ vì các sai lầm tưởng như cơ bản nhưng nó lại phổ biến:
Thiếu hệ thống Monitoring
Monolith thfi vận hành khá đơn giản, tuy nhiên với Microservices thì khác. Hệ thống đồ sộ, dùng nhiều tech-stack, máy chủ phân tán mọi nơi, nhiều lớp, đòi hỏi người vận hành phải có kiến thức tổng quát, và quan trọng là phải có hệ thống Monitor. Với hệ thống Monitor này, người vận hành sẽ dễ dàng kiểm tra được các service nó có "health" hay không, đang chậm, chết ở đâu,… để có kế hoạch ứng phó khi có sự cố hoặc đề phòng sự cố từ trước.
Muốn hệ thống chạy nhanh hơn
Suy nghĩ này có lẽ ai cũng từng nghĩ qua, tuy nhiên kiến trúc Microservices sinh ra không dùng cho mục đích này. Hệ thống muốn chạy nhanh thì phải giải bài toán tối ưu hệ thống, điều chỉnh I/O xuống Database/Disk, caching, load balancing,… dù là Microservices đã giúp chia nhỏ services chạy độc lập, càng nhỏ thì chạy càng nhanh, nhưng nếu không điều chỉnh bài toán tối ưu thì hệ thống vẫn chậm, thậm chí chậm hơn vì phải call đến các services trung gian, remote call.
Không phải cứ chia nhỏ service ra là được
Không phải cứ chia nhỏ service, deploy ra nhiều server thì sẽ được gọi là Microservices. Khi đến với kiến trúc này, sẽ phải tìm hiểu thêm một mớ thứ đi kèm nữa: monitoring, sidecar, service mesh, các công cụ deploy và scaling,… Dù những đồ chơi này không nhất thiết phải có, nhưng chúng lại là những thành phần then chốt giúp hệ thống hoạt động ổn định.
Mặc dù Microservices loại bỏ các mối lệ thuộc trong hệ thống nhưng lại thêm vào rất nhiều rắc rối khác, phải hiểu và biết xài các đồ chơi kia.
Xài chung Database/ Tài nguyên
Nếu làm đúng chuẩn Microservices, sẽ tách riêng cả phần code và phần DB. Mỗi service chỉ được sử dụng DB của riêng nó mà thôi. VD: service Account thì dùng table accounts, service Product thì dùng table products.
Khi chia Db ra sẽ phải đối mặt với nhiều vấn đề sau:
- Chia table sao cho hợp lí, cơ chế đồng bộ, liên kết services phụ thuộc nhau ra sao
- Tính toàn vẹn dữ liệu sẽ biến mất vì phải bỏ ràng buộc khóa ngoại.
- Không thể kết bảng để thực hiện truy vấn, mà phải dùng services-call-service rồi tự handle
- Từ bỏ việc dùng transaction, trigger hay SP giữa các table, các nghiệm vụ chuyên biệt hay viết trong các store procedure/ function/view ở dưới database.
Thiếu vị trí DevOps đúng nghĩa
DevOps nên được tham gia vào ngay từ giai đoạn init dự án thay vì chỉ ở giai đoạn vận hành/deploy. Khi tham gia từ đầu, họ sẽ hiểu rõ vấn đề và hiểu ưu và nhược của các thành phần này, cũng như thực hiện các đo đạc trước khi đưa vào triển khai.
Chiến lược chuyển đổi
Monolith không tệ, thậm chí nó vẫn rất tốt nếu như biết cách tối ưu, Microservices cũng không phải là phức tạp, nếu như quy hoạch bài bản và có kế hoạch cụ thể.
- Lên kế hoạch tách service nhỏ làm trước, đảm nhận một nghiệp vụ nhỏ trước để thử nghiệm, nếu ổn thfi triển tiếp
- Giới hạn scope và quyền của account trên Db thoe chức năng và nghiệp. Khi rào lại sẽ dễ nhận biết sự phụ thuộc giữa các table.
- Xem xét bỏ các khóa ngoại, join table, implement service cơ bản trước, sử dụng remote call (gRPC), Message Queue, hoặc remote API call.
- Tách table, tách code base
- Tiếp tục với các services khác.
- Implement hệ thống Authen/Author
- Load balancing, sidecar, health check,…
- Tối ưu các services, nên dùng API call hay service call?
- Implement hệ thống Logs và các metrics cho toàn bộ services.
- Suy nghĩ về distributed tracing để truy vết được sự cố.
- Thay đổi asyn-call sang message-broker (Kafka,…)
- Hệ thống auto scaling: k8s, terraform,…
Nam Le, nready.net
Nam Le
lequocnam
0 responds