Doge Coin
To The Moon
Microservice Pattern
1. Định nghĩa
Có rất nhiều định nghĩa về microservices. Nhưng chúng ta có thể hiểu đơn giản "microservices là các module/service có thể triển khai (deployable) một cách độc lập, được mô hình hóa dựa trên domain business."
Một module/service như thế, được đóng gói về mặt tính năng và có thể giao tiếp với các module/service khác qua network.
Lấy một ví dụ đơn giản: Một website bán hàng, với các chức năng: Đăng ký người dùng, thanh toán, tìm kiếm sản phẩm v.v...
Các module này có thể được implement một cách độc lập với nhau hoặc phụ thuộc nhau. Ví dụ module tìm kiếm sản phẩm hoàn toàn có thể độc lập với module đăng ký người dùng hoặc thanh toán.
Việc này có thể giúp tăng tốc độ triển khai, giảm số lượng test do các module được phát triển độc lập.
Có thể nói "Independent Deployability" là một trong các core concept của Microservices. Phát triển, thay đổi, cập nhật một cách độc lập mà ko quá phụ thuộc vào các service khác.
Để đảm bảo dc tính chất này, cần đảm bảo các service có tính chất "loosely coupled": Thay đổi một service mà không phải thay đổi bất kỳ service nào khác. Điều này cần một quá trình định nghĩa rõ ràng giữa các service, stable contract với nhau. Đôi khi sẽ trở nên khó khăn nếu lựa chọn "sharing database".
Ngoài ra còn 1 số tính chất khác mình sẽ bổ sung sau vì nó "theory" quá.
Phần tiếp theo này mình sẽ dành thời gian để nói về Timeout Antipattern!
2. Timeout Antipattern
Như ở trên đã nói là các module được deploy một cách độc lập, nên một trong những thử thách trong các kiến trúc phân tán đó chính là làm sao để quản lý được khả năng availability cũng như responsiveness.
- Availablity tức là khả năng mà service consumer kết nối và sử dụng service.
- Responsiveness là thời gian cần để trả lời (respond) một request.
Nếu service consumer không thể kết nối tới service, lúc này service consumer sẽ được notified, và có thể chọn các giải pháp như pass error này tới client, hay retry một vài lần nữa.
Giả sử serivce đã được kết nối với nhau, và thực hiện request nhưng vì 1 lý do gì đó service không đưa ra respond. Trong trường hợp này, service consumer có thể chọn chờ mãi mãi hoặc đặt ra 1 giá trị timeout!
Sử dụng timeout là một cách nhưng nó sẽ dẫn tới timeout anti-pattern!
Câu hỏi là, đặt timeout có phải là tốt hay ko?
Nếu timeout quá nhỏ, một request sắp thành công và "bùm", timeout error happen! Và lúc này bạn phải thực hiện lại request đấy.
Nếu timeouut quá lớn, vậy sẽ phải chờ rất lâu để xác định một request thật sự xảy ra lỗi.
- Có một số cách để ước lượng con số timeout này. Ví dụ dựa vào database timeout, hoặc tính toán khoảng thời gian tối đa xử lý và nhân 2, 3 nó lên như là một extra buffer. Giả sử một request mất tối đa 5 giây, vậy timeout sẽ là 10 giây. Nghĩa là mỗi request từ service consumer cần chờ 10 giây để xác định service not responsive. Nhưng là user thường sẽ chỉ có thể chờ 2-3 giây trước khi hủy thao tác. Do đó cần 1 cơ chế tốt hơn để xử lý vấn đề này.
3. Circuit Breaker Pattern
Khi cầu dao được đóng, dòng điện sẽ chạy qua, và khi mở thì dòng điện sẽ ngừng. Tương tự như thế, trong trường hợp này, một circuit breaker sẽ hoạt động như một chiếc cầu dao.
Nếu circuit breaker phát hiện service không phản hồi lại các request, nó sẽ mở ra, qua đó reject các request gửi tới service. Khi service hoạt động trở lại, circuit breaker sẽ đóng lại.
Để làm việc này thì CB cần liên tục kiểm tra service có đang hoạt động và phản hồi hay không. Khi đó service consumer chỉ cần xem CB đang mở hay đóng. Kết quả này có thể biết được ngay lập tức thay vì phải chờ 1 khoảng thời gian timeout.
(ảnh: google)
CB có thể monitor service thông qua nhiều cách. Cách đơn giản nhất vẫn thường thấy là heartbeat message. Cách này thì chỉ cho chúng ta biết service có đang alive hay không. Ngoài ra ta có thể fake request để gửi tới service, qua đó kiểm tra thông tin service trả về. Một cách thứ ba là real-time user monitoring, theo dõi trực tiếp khả năng đáp ứng của service. Nếu đạt tới một ngưỡng, CB sẽ chuyển sang trạng thái hoạt động một nửa, chỉ 1 số giao dịch được thực hiện. Khi service hoạt động lại bình thường, Cb sẽ đóng lại cho phép mọi request được thực hiện như bình thường.
Nguồn tham khảo:
1. Định nghĩa
Có rất nhiều định nghĩa về microservices. Nhưng chúng ta có thể hiểu đơn giản "microservices là các module/service có thể triển khai (deployable) một cách độc lập, được mô hình hóa dựa trên domain business."
Một module/service như thế, được đóng gói về mặt tính năng và có thể giao tiếp với các module/service khác qua network.
Lấy một ví dụ đơn giản: Một website bán hàng, với các chức năng: Đăng ký người dùng, thanh toán, tìm kiếm sản phẩm v.v...
Các module này có thể được implement một cách độc lập với nhau hoặc phụ thuộc nhau. Ví dụ module tìm kiếm sản phẩm hoàn toàn có thể độc lập với module đăng ký người dùng hoặc thanh toán.
Việc này có thể giúp tăng tốc độ triển khai, giảm số lượng test do các module được phát triển độc lập.
Có thể nói "Independent Deployability" là một trong các core concept của Microservices. Phát triển, thay đổi, cập nhật một cách độc lập mà ko quá phụ thuộc vào các service khác.
Để đảm bảo dc tính chất này, cần đảm bảo các service có tính chất "loosely coupled": Thay đổi một service mà không phải thay đổi bất kỳ service nào khác. Điều này cần một quá trình định nghĩa rõ ràng giữa các service, stable contract với nhau. Đôi khi sẽ trở nên khó khăn nếu lựa chọn "sharing database".
Ngoài ra còn 1 số tính chất khác mình sẽ bổ sung sau vì nó "theory" quá.
Phần tiếp theo này mình sẽ dành thời gian để nói về Timeout Antipattern!
2. Timeout Antipattern
Như ở trên đã nói là các module được deploy một cách độc lập, nên một trong những thử thách trong các kiến trúc phân tán đó chính là làm sao để quản lý được khả năng availability cũng như responsiveness.
- Availablity tức là khả năng mà service consumer kết nối và sử dụng service.
- Responsiveness là thời gian cần để trả lời (respond) một request.
Nếu service consumer không thể kết nối tới service, lúc này service consumer sẽ được notified, và có thể chọn các giải pháp như pass error này tới client, hay retry một vài lần nữa.
Giả sử serivce đã được kết nối với nhau, và thực hiện request nhưng vì 1 lý do gì đó service không đưa ra respond. Trong trường hợp này, service consumer có thể chọn chờ mãi mãi hoặc đặt ra 1 giá trị timeout!
Sử dụng timeout là một cách nhưng nó sẽ dẫn tới timeout anti-pattern!
Câu hỏi là, đặt timeout có phải là tốt hay ko?
Nếu timeout quá nhỏ, một request sắp thành công và "bùm", timeout error happen! Và lúc này bạn phải thực hiện lại request đấy.
Nếu timeouut quá lớn, vậy sẽ phải chờ rất lâu để xác định một request thật sự xảy ra lỗi.
- Có một số cách để ước lượng con số timeout này. Ví dụ dựa vào database timeout, hoặc tính toán khoảng thời gian tối đa xử lý và nhân 2, 3 nó lên như là một extra buffer. Giả sử một request mất tối đa 5 giây, vậy timeout sẽ là 10 giây. Nghĩa là mỗi request từ service consumer cần chờ 10 giây để xác định service not responsive. Nhưng là user thường sẽ chỉ có thể chờ 2-3 giây trước khi hủy thao tác. Do đó cần 1 cơ chế tốt hơn để xử lý vấn đề này.
3. Circuit Breaker Pattern
Khi cầu dao được đóng, dòng điện sẽ chạy qua, và khi mở thì dòng điện sẽ ngừng. Tương tự như thế, trong trường hợp này, một circuit breaker sẽ hoạt động như một chiếc cầu dao.
Nếu circuit breaker phát hiện service không phản hồi lại các request, nó sẽ mở ra, qua đó reject các request gửi tới service. Khi service hoạt động trở lại, circuit breaker sẽ đóng lại.
Để làm việc này thì CB cần liên tục kiểm tra service có đang hoạt động và phản hồi hay không. Khi đó service consumer chỉ cần xem CB đang mở hay đóng. Kết quả này có thể biết được ngay lập tức thay vì phải chờ 1 khoảng thời gian timeout.
(ảnh: google)
CB có thể monitor service thông qua nhiều cách. Cách đơn giản nhất vẫn thường thấy là heartbeat message. Cách này thì chỉ cho chúng ta biết service có đang alive hay không. Ngoài ra ta có thể fake request để gửi tới service, qua đó kiểm tra thông tin service trả về. Một cách thứ ba là real-time user monitoring, theo dõi trực tiếp khả năng đáp ứng của service. Nếu đạt tới một ngưỡng, CB sẽ chuyển sang trạng thái hoạt động một nửa, chỉ 1 số giao dịch được thực hiện. Khi service hoạt động lại bình thường, Cb sẽ đóng lại cho phép mọi request được thực hiện như bình thường.
Nguồn tham khảo:
- Hystrix Netflix
- Akka framework https://akka.io/
- https://martinfowler.com/bliki/CircuitBreaker.html
- O'reilly: Microservice antipatterns and pitfalls
Last edited: