Các mẫu design pattern hiện đại

Ngày nay, nhiều ứng dụng hiện đại cần được xây dựng ở quy mô doanh nghiệp, đôi khi thậm chí ở quy mô internet. Mỗi ứng dụng cần đáp ứng các nhu cầu về khả năng mở rộng (scalability), tính khả dụng (availability), bảo mật (security), độ tin cậy (reliability) và khả năng phục hồi (resiliency demands).

Trong bài viết này, tôi sẽ nói về một số mẫu thiết kế (design pattern) có thể giúp bạn đạt được những khả năng nêu trên một cách dễ dàng. Tôi sẽ nói về từng mẫu, cách sử dụng mẫu đó trong môi trường đám mây (cloud), khi nào thì sử dụng và khi nào thì không.

Một số mẫu thiết kế không quá mới nhưng rất hữu ích trong thế giới đám mây quy mô internet hiện tại.

Đây là danh sách các mẫu thiết kế tôi sẽ thảo luận trong bài viết này:

  • Circuit Breaker
  • Command and Query Responsibility (CQRS)
  • Event Sourcing
  • Sidecar
  • Backend-for-Frontend (BFF)
  • Strangler

Vậy hãy bắt đầu nào.

Circuit Breaker

Các hệ thống phân tán (distributed system) phải được thiết kế bằng cách xem xét các khía cạnh hỏng hóc. Ngày nay, thế giới đã áp dụng microservices và các dịch vụ này thường phụ thuộc vào các dịch vụ từ xa khác. Các dịch vụ từ xa này có thể không phản hồi kịp thời do nhiều lý do khác nhau như mạng, tải ứng dụng, v.v. Trong hầu hết các trường hợp, việc thử lại sẽ có thể giải quyết vấn đề.

Nhưng đôi khi có thể có những vấn đề lớn như dịch vụ dừng hoạt động tạm thời hoặc dịch vụ gặp sự cố phải dừng hoạt động hoàn toàn. Thật vô nghĩa nếu bạn tiếp tục thử lại trong những trường hợp như vậy. Đó là nơi mà mẫu Circuit Breaker có thể hữu ích.

Circuit Breaker

Sơ đồ trên giới thiệu việc triển khai mẫu Circuit Breaker, trong đó khi Service 1 hiểu rằng có lỗi hoặc timeout liên tục khi gọi Service 2. Thay vì thử lại, Service 1 chuyển hướng các cuộc gọi đến Service 2 và trả về phản hồi dự phòng.

Có những thư viện nguồn mở phổ biến được sử dụng để triển khai mẫu này rất dễ dàng như Hystrix của Netflix hoặc Reselience4J.

Nếu bạn đang sử dụng API Gateway hoặc Sidecar proxy như Envoy thì cũng có thể đạt được điều tương tự ở cấp proxy.

Lưu ý: Một điều rất quan trọng là phải ghi log đầy đủ và cảnh báo ngay khi Circuit Breaker được kích hoạt để theo dõi các yêu cầu nhận được trong thời gian này và nhóm vận hành biết về điều này.

Khi nào nên sử dụng mẫu này

  • Khi một dịch vụ phụ thuộc vào một dịch vụ từ xa khác và nó có khả năng bị lỗi trong một số trường hợp.
  • Khi một dịch vụ có mức độ phụ thuộc rất cao (ví dụ: dịch vụ dữ liệu chính).

Khi nào không nên sử dụng mẫu này

  • Khi bạn đang xử lý các phần phụ thuộc cục bộ - Circuit Breaker có thể tạo thêm chi phí.

Command and Query Responsibility (CQRS)

CQRS là một design pattern rất hữu ích cho các ứng dụng hiện đại liên quan đến việc sử dụng các kho dữ liệu. Nó dựa trên nguyên tắc tách biệt các hoạt động đọc (Query) và ghi / cập nhật (Command) trong một kho dữ liệu.

Giả sử bạn đang xây dựng một ứng dụng yêu cầu bạn lưu trữ dữ liệu trong cơ sở dữ liệu như MySQL / PostgreSQL, v.v. Như mọi người đều biết, khi ghi dữ liệu vào kho dữ liệu, một hoạt động cần thực hiện một số bước - như xác thực, mô hình và lưu trữ - và do đó các thao tác ghi / cập nhật mất nhiều thời gian hơn các thao tác đọc đơn giản.

Khi bạn đang sử dụng một cơ sở dữ liệu duy nhất để thực hiện cả thao tác đọc và ghi cùng một lúc và ở quy mô lớn, thì bạn có thể bắt đầu thấy các vấn đề về hiệu suất.

Trong những trường hợp như vậy, mẫu CQRS có thể hữu ích. Mẫu CQRS đề xuất sử dụng các mô hình dữ liệu khác nhau cho các hoạt động đọc và ghi. Một số biến thể cũng đề xuất sử dụng kho dữ liệu riêng biệt cho các mô hình này.

Command and Query Responsibility (CQRS)

Nhiều cơ sở dữ liệu doanh nghiệp cũng cung cấp khả năng này nếu bạn đang xử lý cơ sở dữ liệu tại chỗ.

Lưu ý: Ngày nay, một số lập trình viên thích sử dụng cơ sở dữ liệu NoSQL nhanh và hiệu quả như MongoDB và Elasticsearch để làm database đọc.

Tham khảo thêm về CQRS ở bài viết này:

CQRS là gì?
CQRS pattern là sự kết hợp các khái niệm về CQS, Command, Query và CommandBus, Single Responsibility Principle.

Khi nào nên sử dụng mẫu này

  • Khi bạn đang xem xét việc mở rộng một ứng dụng có số lượng các thao tác đọc và ghi rất lớn.
  • Khi bạn muốn điều chỉnh hiệu suất của các thao tác đọc và ghi riêng biệt.
  • Khi bạn chấp nhận thao tác đọc gần như thời gian thực hoặc tính nhất quán  sau cùng.

Khi nào không nên sử dụng mẫu này

  • Khi bạn đang xây dựng một ứng dụng CRUD thông thường không có lượng lớn các lần đọc và ghi cùng một lúc.

Event Sourcing

Event Sourcing là một mẫu thiết kế thú vị trong đó một chuỗi các sự kiện miền được lưu trữ dưới dạng nhật ký và khi duyệt qua tập hợp các nhật ký này sẽ cho biết trạng thái hiện tại của ứng dụng.

Mẫu này thường được sử dụng cho các hệ thống không có khả năng khóa lưu trữ dữ liệu và cần duy trì việc kiểm tra và lịch sử của các sự kiện - ví dụ: các ứng dụng đặt phòng khách sạn / hội nghị / chỗ ngồi.

Event Sourcing

Xem xét một hệ thống đặt phòng khách sạn trong đó người dùng dự kiến ​​sẽ đặt hoặc hủy đặt phòng. Tại đây, bạn cần lưu trữ các lượt đặt và lượt hủy dưới dạng một chuỗi các sự kiện. Trước mỗi lượt đặt phòng, duyệt qua tập hợp các nhật ký sẽ hiển thị các phòng trống.

Lưu ý: Hầu hết các nhà cung cấp dịch vụ đám mây đều hỗ trợ các dịch vụ nhắn tin như Google Pub / Sub, Azure Service Bus, AWS SQS, v.v. Những dịch vụ này, kết hợp với kho dữ liệu nhất quán mạnh, có thể được sử dụng để triển khai mẫu này.

Khi nào nên sử dụng mẫu này

  • Khi hoạt động CRUD thông thường không đủ tốt để đáp ứng nhu cầu.
  • Thường phù hợp với các hệ thống đặt chỗ - như xe buýt, xe lửa, hội nghị, phòng chiếu phim, v.v. - hoặc hệ thống thương mại điện tử bao gồm các sự kiện như hoạt động giỏ hàng, thanh toán, v.v.
  • Khi có yêu cầu kiểm tra mạnh mẽ và phát lại các sự kiện để tạo trạng thái hiện tại và quá khứ của ứng dụng.

Khi nào không nên sử dụng mẫu này

  • Khi thao tác CRUD đủ tốt để đáp ứng nhu cầu của người dùng.

Sidecar

Các mẫu Sidecar trở nên phổ biến với sự trỗi dậy của microservices. Trong mẫu này, bạn triển khai một thành phần của ứng dụng vào một quy trình hoặc một vùng chứa riêng biệt. Điều này giúp đạt được sự trừu tượng và đóng gói.

Envoy Proxy là một trong những proxy sidecar phổ biến nhất và được sử dụng rộng rãi. Nó giúp bạn tách biệt chức năng cốt lõi của ứng dụng, sử dụng sidecar để tách biệt các tính năng chung như mạng, khả năng quan sát và bảo mật.

Sidecar

Loại sidecar như vậy có thể giúp kiểu giao tiếp trừu tượng L4 / L7. Sidecar như Envoy Proxy thậm chí còn giúp đạt được tính bảo mật cao hơn bằng cách triển khai TLS lẫn nhau.

Bạn có thể sử dụng điều này kết hợp với lưới dịch vụ (service mesh) để đạt được giao tiếp và bảo mật tốt hơn giữa các microservices khác nhau.

Vai trò của Service Mesh và API Gateway trong Microservices
Trong bài viết này, tôi sẽ nói chi tiết về Service Mesh (lưới dịch vụ), API Gateway trong Microservices và thảo luận khi nào thì sử dụng chúng.

Khi nào nên sử dụng mẫu này

  • Khi bạn xử lý nhiều microservices và không đồng nhất trong phạm vi sản phẩm.
  • Khi bạn đang xử lý các ứng dụng cũ thường không đủ khả năng đối phó với các thách thức bảo mật và giao tiếp thời đại mới.

Khi nào không nên sử dụng mẫu này

  • Khi bạn đang xử lý một số dịch vụ hạn chế cần giao tiếp với nhau.
  • Các ứng dụng nhỏ trong đó triển khai sidecar có thể không kinh tế hoặc không thân thiện với hoạt động.

Backend-for-Frontend (BFF)

Trong một chu kỳ phát triển sản phẩm điển hình, các kỹ sư backend chịu trách nhiệm tạo ra các dịch vụ tương tác với các kho dữ liệu và các kỹ sư frontend sẽ đảm nhận việc xây dựng giao diện người dùng. Ngày nay, các ứng dụng cần được xây dựng để lưu ý đến việc sử dụng thiết bị di động cũng như máy tính để bàn.

Mặc dù khoảng cách giữa thiết bị di động và máy tính để bàn về mặt phần cứng ngày càng gần, nhưng kết nối và sử dụng vẫn tiếp tục là thách thức đối với các thiết bị di động.

Trong các tình huống như vậy, các mẫu BFF trở nên khá tiện dụng. Tại đây, bạn dự kiến ​​sẽ xây dựng / tùy chỉnh các dịch vụ backend cho giao diện người dùng cụ thể.

Backend-for-Frontend (BFF)

Để tối ưu hóa hiệu suất của máy khách di động, bạn có thể muốn xây dựng một dịch vụ back-end riêng biệt đáp ứng các phản hồi nhẹ và được phân trang.

Bạn cũng có thể muốn sử dụng mẫu này để tổng hợp các dịch vụ khác nhau nhằm giảm bớt giao tiếp.

Lưu ý: Ngày nay nếu bạn đang sử dụng API Gateway, mẫu BFF có thể được triển khai dễ dàng trong chính API Gateway đó và bạn không cần phải duy trì các dịch vụ riêng biệt.

Khi nào nên sử dụng mẫu này

  • Khi bạn muốn cung cấp một sản phẩm / dịch vụ cho các loại client khác nhau như máy tính để bàn và thiết bị di động.
  • Khi bạn muốn tối ưu hóa phản hồi cho một loại client cụ thể.
  • Khi bạn muốn giảm giao tiếp giữa các client di động và các dịch vụ khác.

Khi nào không sử dụng mẫu này

  • Khi người dùng ứng dụng được mong đợi sử dụng một giao diện người dùng
  • Khi các ứng dụng dành cho thiết bị di động và máy tính để bàn sẽ hiển thị thông tin tương tự và cung cấp chức năng tương tự

Strangler

Nếu bạn đang làm việc trong một tổ chức đang trên hành trình hướng tới hiện đại hóa ứng dụng, thì mẫu thiết kế Strangler là bắt buộc. Mẫu thiết kế Strangler ủng hộ việc tạo ra một mặt tiền trên di sản của bạn và một ứng dụng mới, cung cấp một cái nhìn trừu tượng cho người tiêu dùng.

Strangler

Mô hình này tách người tiêu dùng khỏi các hoạt động di chuyển.

Lưu ý: Trong một tổ chức CNTT điển hình, nếu bạn đang chuyển từ ERP này sang ERP khác, design pattern này cực kỳ hữu ích. Nếu bạn đang sử dụng API Gateway, việc triển khai điều này thậm chí còn dễ dàng hơn.

Bạn cần quyết định xem bạn muốn giữ mặt tiền khi kết thúc quá trình di chuyển hay loại bỏ nó.

Khi nào nên sử dụng mẫu này

  • Khi bạn đang di chuyển hoặc hiện đại hóa một ứng dụng phức tạp, phụ thuộc nhiều như di chuyển ERP.

Khi nào không nên sử dụng mẫu này

  • Khi việc di chuyển đơn giản và thay thế trực tiếp là một lựa chọn tốt hơn.
Design PatternCQRS PatternSidecarBFFCircuit BreakerEvent SourcingStrangler Pattern
Bài Viết Liên Quan:
Design Patterns: Visitor
Trung Nguyen 15/01/2021
Design Patterns: Visitor

Visitor là một mẫu thiết kế hành vi cho phép bạn tách các thuật toán khỏi các đối tượng mà chúng hoạt động.

Design Patterns: Template Method
Trung Nguyen 15/01/2021
Design Patterns: Template Method

Template Method định nghĩa khung của một thuật toán trong lớp cha cho phép lớp con ghi đè các bước cụ thể của thuật toán mà không thay đổi cấu trúc của nó.

Design Patterns: Strategy
Trung Nguyen 15/01/2021
Design Patterns: Strategy

Strategy cho phép bạn định nghĩa một nhóm thuật toán, đặt mỗi thuật toán vào một lớp riêng biệt và làm cho các đối tượng của chúng có thể hoán đổi cho nhau.

Design Patterns: State
Trung Nguyen 15/01/2021
Design Patterns: State

State là một mẫu thiết kế hành vi cho phép một đối tượng thay đổi hành vi của nó khi trạng thái bên trong của nó thay đổi.