MICROSERVICES LÀ GÌ VÀ HIỂU TƯỜNG TẬN VỀ MICROSERVICES
1. Microservice là gì?
Microservice là một kiểu kiến trúc mà nó gần như là chia nhỏ các chức năng và các dịch vu xử lý ra. Hiểu đơn giản là chia để trị. Mỗi dịch vụ sẽ được đặt trên một server riêng (nếu có đủ điều kiện) để có thể dễ dàng để nâng cấp hoặc chỉnh sửa ứng dụng. Có thể thuê nhiều đơn vị khác nhau làm từng service khác nhau mà không ảnh hưởng gì đến dự án. Các service chạy độc lập với nhau hoặc giao tiếp với nhau.
Hiểu đơn giản là nó tách nhỏ các chức năng ra làm 1 dịch vụ riêng lẽ độc lập và gần như không liên quan gì đến nhau. Chúng giao tiếp với nhau qua rất nhiều phương thức như rest API hay là GRPC hoặc có thể là lambda hoặc bất cứ phương thức nào có thể giao tiếp được.
Ưu điểm của giải pháp này thì quá rõ ràng. Với các dịch vụ được tách nhỏ độc lập như vậy thì các bạn hoàn toàn có thể nâng cấp, bảo trì bổ sung từng riêng lẻ mà không hề làm ảnh hưởng tới cả tổng thể của cả 1 dự án.
2. Những đặc điểm của microservice
Decoupling - Các service trong một hệ thống phần lớn được tách rời. Vì vậy, toàn bộ ứng dụng có thể dễ dàng được xây dựng, thay đổi và thu nhỏ.
Componentization - Microservices được coi là các thành phần độc lập có thể dễ dàng thay thế và nâng cấp.
Business Capabilities - mỗi một thành phần trong kiến trúc microservice rất đơn giản và tập trung vào một nhiệm vụ duy nhất.
Autonomy - các lập trình viên hay các nhóm có thể làm việc độc lập với nhau trong quá trình phát triển.
Continous Delivery - Cho phép phát hành phần mềm thường xuyên, liên tục.
Responsibility.
Decentralized Governance - không có mẫu chuẩn hóa hoặc bất kỳ mẫu công nghệ nào. Được tự do lựa chọn các công cụ hữu ích tốt nhất để có thể giải quyết vấn đề.
Agility - microservice hỗ trợ phát triển theo mô hình Agile.
3. Ưu điểm của Microservices
- Giảm thiểu sự gia tăng phức tạp rối rắm hệ thống lớn.
- Chia nhỏ ứng dụng một khối cồng kềnh thành các dịch vụ nhỏ dễ quản lý, bảo trì nâng cấp, tự do chọn, nâng cấp công nghệ mới.
- Mỗi dịch vụ nhỏ sẽ định ra ranh giới rõ ràng dưới dạng RPC hay API hướng thông điệp.
- Microservice thúc đẩy tách rạch ròi các khối chức năng (Loose Coupling- High Cohesion), điều rất khó thực hiện với ứng dụng một khối. Nếu muốn Loose Coupling- High Cohesion trong ứng dụng một khối, sẽ phải thiết kế theo Design Pattern (Gang Of Four) và liên tục tái cấu trúc (Refactor)
Mỗi dịch vụ nhỏ thì sẽ phát triển dễ hơn, nhanh hơn và đơn giản hoá các công đoạn khác như Test, Release...
4. Nhược điểm của Microservices
Nhược điểm đầu tiên của Microservices cũng chính từ tên gọi của nó. Microservice nhấn mạnh kích thước nhỏ gọn của dịch vụ. Một số lập trình đề xuất dịch vụ siêu nhỏ cỡ dưới 100 dòng code. Chia quá nhiều sẽ dẫn đến manh mún, vụn vặt, khó kiểm soát. Việc lưu dữ liệu cục bộ bên trong những dịch vụ quá nhỏ sẽ khiến dữ liệu phân tán quá mức cần thiết.
Nhược điểm tiếp của Microservice đến từ đặc điểm hệ thống phân tán (Distributed System):
- Phải xử lý sự cố khi kết nối chậm, lỗi khi thông điệp không gửi được hoặc thông điệp gửi đến nhiều đích đến vào các thời điểm khác nhau.
- Đảm bảo giao dịch phân tán (Distributed Transaction) cập nhật dữ liệu đúng đắn (All or None) vào nhiều dịch vụ nhỏ khác nhau khó hơn rất nhiều, đôi khi là không thể so với đảm bảo giao dịch cập nhật vào nhiều bảng trong một cơ sở dữ liệu trung tâm.
- Theo nguyên tắc CAP (CAP theorem) thì giao dịch phân tán sẽ không thể thỏa mãn cả 3 điều kiện: Consistency (dữ liệu ở điểm khác nhau trong mạng phải giống nhau), Availablity (yêu cầu gửi đi phải có phúc đáp), Partition Tolerance (hệ thống vẫn hoạt động được ngay cả khi mạng bị lỗi). Những công nghệ cơ sở dữ liệu phi quan hệ (NoSQL) hay môi giới thông điệp (Message Broker) tốt nhất hiện nay cũng chưa vượt qua nguyên tắc CAP.
- Kiểm thử tự động một dịch vụ trong kiến trúc Microservices đôi khi yêu cầu phải chạy cả các dịch vụ nhỏ khác mà nó phụ thuộc. Do đó khi phân rã ứng dụng một khối thành Microservices cần luôn kiểm tra mức độ ràng buộc giữa các dịch vụ mềm dẻo hơn hay cứng nhắc- lệ thuộc hơn. Nếu ràng buộc ít đi, lỏng leo hơn, bạn đi đúng hướng và ngược lại.
- Nếu các dịch vụ nhỏ thiết kế phục thuộc vào nhau theo chuỗi. A gọi B, B gọi C, C gọi D. Nếu một mắt xích có giao tiếp API thay đổi, liệu các mắt xích khác có phải thay đổi theo không? Nếu có thì việc bảo trì, kiểm thử sẽ phức tạp tương tự ứng dụng một khối. Thiết kế dịch vụ tốt sẽ giảm tối đa ảnh hưởng lan truyền đến các dịch vụ khác. thay đổi lan truyền trong ứng dụng khiến cho việc nâng cấp, kiểm tra khó khăn hơn
- Cuộc họp có 2 người sẽ có 1 bắt tay, 3 người có 3 bắt tay. 4 người có 6 bắt tay, 5 có 10 bắt tay. Tổ hợp chập 2 của 5 = 10, công thức tổng quát = n! /((n-2)! * 2!). Thực thế không phải dịch vụ nào trong Microservice cũng sẽ giao tiếp với tất cả những dịch vụ còn lại. Nhưng nếu không có quy tắc phân luồng - quản lý - đo đếm - theo dõi (Manage- Meter- Monitor), thì số lượng kết nối giữa các dịch vụ nhỏ gia tăng tùy tiện, chất lượng kết nối không kiểm soát. Hệ thống chậm nhưng không thể biết đoạn nghẽn cổ chai ở đâu? Kết nối giữa các dịch vụ có thể rối rắm như thế này.
- Triển khai dịch vụ Microservices nếu làm thủ công theo cách đã làm với ứng dụng một khối phức tạp hơn rất nhiều. Ứng dụng một khối bổ sung các server mới giống hệt nhau đằng sau bộ cần bằng tại. Trong khi ở kiến trúc Microservice, các dịch vụ nhỏ nằm trên nhiều máy ảo hay Docker container khác nhau, hoặc một dịch vụ có nhiều thực thể phân tán ra nhiều. Theo Adrian Crockcroft, Hailo có 160 dịch vụ, NetFlix có hơn 600 dịch vụ. Trong dịch vụ đám mây, các máy ảo, docker container, thực thể có thể linh động bật tắt, dịch chuyển. Vậy cần thiết phải có một cơ chế phát hiện dịch vụ (Service Discovery Mechanism) để cập nhật tự động địa chỉ IP và cổng, mô tả, phiên bản của mỗi dịch vụ.
5. Kiến trúc Microservices
Khác biệt với kiến trúc Monolith, hay vì gom tất cả module thành một khối (Monolith), ta tách các module thành những service siêu nhỏ. Mỗi service sẽ được đặt trên một server riêng (Có thể dùng server cloud như AWS hoặc Azure), giao tiếp với nhau thông qua mạng (Gửi nhận message qua giao thức HTTP hoặc sử dụng MessageQueue).
6. Liên lạc giữa Microservices
Có thể bạn sẽ thắc mắc rằng các microservices liên lạc với nhau như thế nào đúng không. Ở đây tôi sẽ liệt kê các loại liên kết thường dùng của các ứng dụng Microservices.
Gửi Tin Đồng Bộ - REST, Thrift
Với truyền tin đồng bộ (người gửi - client sẽ chờ một khoảng thời gian để nhận kết quả từ service), REST là sự lựa chọn hàng đầu vì nó cung cấp hệ thống truyền tin đơn giản qua giao thức HTTP dạng request - response. Do đó, nhiều microservices sử dụng HTTP với API. Mỗi chức năng xuất ra API.
Gửi Tin Bất Đồng Bộ - AMQP, STOMP, MQTT
Trong một số hoàn cảnh, truyền tin bất đồng bộ là cần thiết (client không mong đợi response ngay lập tức, hoặc không cần response). Các giao thức truyền tin bất đồng bộ như AMQP, STOMP hay MQTT được sử dụng rộng rãi.
Các Kiểu Tin Nhắn - JSON, XML, Thrift, ProtoBuf, Avro
Quyết định kiểu tin nhắn phù hợp cho microservices cũng là một yếu tố quan trọng. Với phần lớn các ứng dụng microservices, họ sử dụng những kiểu tin nhắn dạng chữ như JSON và XML trên nền giao thức HTTP với API. Trong trường hợp cần truyền tin dạng nhị phân, microservices có thể dùng dạng Thrift, Proto hay Avro.
Service Contracts - Định Nghĩa Service Interfaces - Swagger, RAML
Khi bạn có một nghiệp vụ được xây dựng như một dịch vụ, bạn cần định nghĩa và thông báo hợp đồng dịch vụ (service contract thể hiện giao kèo của service).
Bởi vì chúng ta xây dựng microservices trên kiểu kiến trúc REST, ta có thể sử dụng cùng kiểu REST API để định nghĩa hợp đồng của microservices. Do đó, microservices sử dụng các ngôn ngữ định nghĩa REST API tiêu chuẩn như Swagger, RAML để định nghĩa hợp đồng dịch vụ.
7. Sự khác biệt giữa API và Microservice
Dưới đây là những khác biệt chính giữa API và microservice:
- API là một tập hợp các định nghĩa chương trình con, giao thức truyền thông và các công cụ để xây dựng phần mềm. Nói chung, nó là một tập hợp các phương thức giao tiếp được xác định rõ ràng giữa các thành phần khác nhau.
- Microservice là một thiết kế kiến trúc tách các phần của ứng dụng (thường là nguyên khối) chia thành các dịch vụ nhỏ, tự vận hành.
Theo định nghĩa, điều này có nghĩa là API thường là một phần của microservice, cho phép tương tác với chính microservice. Một cách khác để suy nghĩ về điều này là API đóng vai trò là hợp đồng cho các tương tác trong Microservice, trình bày các tùy chọn có sẵn để tương tác với Microservice.
Tuy nhiên, nếu chúng ta nhìn vào sơ đồ Microservice ở trên, chúng ta có thể thấy rằng mỗi Mcroservice được xây dựng hơi khác nhau dựa trên nhu cầu của nó. Dưới đây là một vài ví dụ về các chức năng khác nhau mà microservice có thể có:
- Cung cấp các hoạt động CRUD cho một loại thực thể cụ thể, chẳng hạn như khách hàng, sự kiện, v.v. Dịch vụ này sẽ giữ khả năng duy trì dữ liệu trong cơ sở dữ liệu.
- Cung cấp một phương tiện để chấp nhận các tham số và trả về kết quả dựa trên các tính toán (có khả năng dữ dội). Dịch vụ siêu nhỏ thanh toán ở trên có thể lấy thông tin về một sự kiện hoặc khách hàng và trả lại thông tin thanh toán cần thiết mà không cần lưu trữ dữ liệu.
Với ví dụ trên, có lẽ bạn có thể thấy rằng microservice có khả năng không chỉ là một API cho một hệ thống. Toàn bộ ứng dụng có thể bao gồm một loạt các dịch vụ siêu nhỏ sử dụng API riêng để liên lạc với nhau. Ngoài ra, mỗi dịch vụ siêu nhỏ này có thể trừu tượng hóa chức năng của chính nó, vẽ ranh giới logic cho trách nhiệm trong ứng dụng và tách biệt các mối quan tâm để tạo ra một cơ sở mã hóa dễ bảo trì hơn.