🔴 Nâng cao · Bài 11 / 14

Messaging bất đồng bộ

Cách các service giao tiếp gián tiếp & bất đồng bộ để decouple: Message Brokers, Queues, Pub/Sub, ESB, và các pattern EDA, Event Sourcing, CQRS.

Message Brokers

Phần mềm trung gian cho phép các ứng dụng/service giao tiếp & trao đổi thông tin — dịch message giữa các giao thức. Sender gửi mà không cần biết receiver ở đâu, còn sống không, hay có bao nhiêu → giúp decoupling.

Hai mô hình phân phối: Point-to-Point (one-to-one, dùng trong message queue) và Publish-Subscribe (one-to-many). Ví dụ: Kafka, RabbitMQ, NATS, ActiveMQ.

Message Broker
Message broker làm trung gian, giúp các service decouple khỏi nhau

Message Queues

Giao tiếp bất đồng bộ service-to-service. Message lưu trong queue đến khi được xử lý & xóa — mỗi message chỉ xử lý một lần bởi một consumer.

Producer ──▶ [ msg | msg | msg ] ──▶ Consumer (Queue lưu đến khi xử lý xong)
Message Queue
Message queue — mỗi message chỉ được xử lý một lần bởi một consumer

Ưu điểm: Scalability, Decoupling, Performance (bất đồng bộ), Reliability (persistent).

Tính năng quan trọng: Push/Pull delivery, FIFO, scheduled/delay, at-least-once / exactly-once delivery, Dead-letter queue (chứa message không xử lý được), ordering best-effort, security.

⚠️ Backpressure

Nếu queue phình quá lớn vượt bộ nhớ → chậm. Backpressure giới hạn kích thước queue; khi đầy, client nhận "server busy" / HTTP 503 để thử lại sau (dùng exponential backoff). Ví dụ: Amazon SQS, RabbitMQ.

Publish-Subscribe (Pub/Sub)

Khác queue: message publish lên một topic sẽ được đẩy (push) ngay tới TẤT CẢ subscriber của topic. Mỗi subscriber làm việc khác nhau với message, song song.

┌─▶ Subscriber A Publisher ─▶ Topic ─┼─▶ Subscriber B (fanout — song song) └─▶ Subscriber C
Publish-Subscribe
Pub/Sub — message lên topic được đẩy tới TẤT CẢ subscriber (fanout)

Ưu điểm: bỏ polling (push tức thì), dynamic targeting, decoupled & scale độc lập, đơn giản hóa giao tiếp. Tính năng: push delivery, multiple protocols, fanout, filtering, durability, security. Ví dụ: Amazon SNS, Google Pub/Sub.

Enterprise Service Bus (ESB)

Mẫu kiến trúc cũ với một component tập trung lo tích hợp giữa các ứng dụng. Nhược: single point of failure, cấu hình & bảo trì phức tạp, update dễ ảnh hưởng integration khác. → Message broker là giải pháp nhẹ hơn, phù hợp microservices hơn ESB.

Enterprise Service Bus
ESB — một bus tập trung tích hợp mọi ứng dụng (dễ thành điểm chết)

Event-Driven Architecture (EDA)

Dùng event làm phương thức giao tiếp, thường qua message broker, publish/consume bất đồng bộ. Một event là data point biểu diễn thay đổi trạng thái — không ra lệnh phải làm gì, chỉ thông báo "đã có gì xảy ra".

3 thành phần: Event producers → Event routers → Event consumers. Ưu: decouple producer/consumer, scale tốt, dễ thêm consumer. Thách thức: đảm bảo delivery, xử lý lỗi, exactly-once & đúng thứ tự.

Event-Driven Architecture
EDA — producer → router → consumer, giao tiếp bằng event

Event Sourcing

Thay vì chỉ lưu trạng thái hiện tại, dùng kho append-only ghi lại toàn bộ chuỗi hành động. Kho event là "system of record"; trạng thái được tái dựng (materialize) từ các event.

ℹ️ Event Sourcing vs EDA

EDA dùng event để giao tiếp giữa các service. Event Sourcing dùng event làm cách lưu trữ state (lưu event thay vì current state). Event Sourcing là một pattern để triển khai EDA. Ưu: tuyệt cho audit log, fail-safety (tái dựng từ event), linh hoạt.

Event Sourcing
Event Sourcing — lưu toàn bộ chuỗi event (append-only) thay vì chỉ state hiện tại

CQRS (Command Query Responsibility Segregation)

Tách hành động hệ thống thành Command (thay đổi state, không trả value) và Query (đọc thông tin, không side-effect). Mô tả lần đầu bởi Greg Young.

Command (write) ──▶ Write Model ──▶ [Event Store] │ Query (read) ◀── Read Model ◀── materialized view (denormalized)
CQRS
CQRS — tách model ghi (Command) và model đọc (Query) riêng biệt

Thường dùng cùng Event Sourcing: event store là write model (nguồn chính thức), read model là view denormalized tối ưu cho đọc.

Ưu: scale read/write độc lập, tối ưu riêng, tránh join phức tạp, ranh giới rõ. Nhược: thiết kế phức tạp hơn, xử lý eventual consistency khó, tăng effort bảo trì.

✅ Tóm tắt bài 11

Message broker làm trung gian decouple. Queue: 1 message → 1 consumer (chú ý backpressure, DLQ). Pub/Sub: 1 message → mọi subscriber (fanout). ESB cũ & nặng → ưu tiên broker. EDA giao tiếp bằng event; Event Sourcing lưu state bằng event; CQRS tách đọc/ghi (hay đi cùng Event Sourcing).