T2 — Kiến trúc hướng sự kiện (EDA) - congsinhv/fluxion GitHub Wiki

Kiến Trúc Hướng Sự Kiện (Event-Driven Architecture) trong Hệ Thống MDM

Issue: #10 — Nghiên cứu kiến trúc hướng sự kiện (EDA) Tuần: 2 (31/03 – 06/04/2026) Numbering chính thức: Mục 2.2 theo Master TOC (Chương 2)


2.2.1 Tổng Quan về Kiến Trúc Hướng Sự Kiện

Định Nghĩa

Kiến trúc hướng sự kiện (Event-Driven Architecture — EDA) là mô hình kiến trúc phần mềm trong đó các thành phần giao tiếp thông qua việc phát sinh (produce) và tiêu thụ (consume) các sự kiện. Một sự kiện là bản ghi bất biến (immutable record) phản ánh một thực tế đã xảy ra tại thời điểm xác định [1][4].

Theo Hohpe & Woolf (2003) trong Enterprise Integration Patterns, EDA là nền tảng của các hệ thống tích hợp doanh nghiệp hiện đại, cho phép tách biệt hoàn toàn giữa các thành phần thông qua truyền thông điệp bất đồng bộ [1].

Michelson (2006) trong bài tổng quan Event-Driven Architecture Overview phân loại EDA thành ba lớp: xử lý sự kiện đơn giản (simple event processing), xử lý luồng sự kiện (event stream processing), và xử lý sự kiện phức hợp (complex event processing — CEP). MDM chủ yếu sử dụng lớp đầu tiên — mỗi sự kiện kích hoạt một phản ứng tương ứng [4].

Newman (2015) trong Building Microservices nhận định giao tiếp hướng sự kiện là phương pháp tối ưu để kết nối các microservice vì loại bỏ sự phụ thuộc trực tiếp giữa các dịch vụ [5].

Các Thành Phần Cốt Lõi

1. Bộ phát sinh sự kiện (Event Producer)

Thực thể phát hiện thay đổi trạng thái và phát ra thông điệp sự kiện. Producer hoàn toàn không biết về sự tồn tại của Consumer — đây là nguyên tắc tách biệt cốt lõi của EDA [1].

2. Kênh truyền sự kiện (Event Channel)

Hạ tầng trung gian tiếp nhận, đệm (buffer), định tuyến, và phân phối sự kiện tới Consumer. Theo Hohpe & Woolf (2003), bao gồm hai mô hình chính [1]:

  • Hàng đợi điểm-điểm (Point-to-Point Queue): Một sự kiện được tiêu thụ bởi đúng một Consumer (ví dụ: AWS SQS)
  • Chủ đề đăng ký-phát hành (Publish-Subscribe Topic): Một sự kiện được phân phối đến tất cả Consumer đã đăng ký (ví dụ: AWS SNS, Apache Kafka topic)

3. Bộ tiêu thụ sự kiện (Event Consumer)

Thành phần lắng nghe Event Channel và thực thi logic nghiệp vụ khi nhận sự kiện. Consumer phản ứng bất đồng bộ, không chặn (block) Producer [1].


2.2.2 So Sánh EDA và Kiến Trúc Yêu Cầu-Phản Hồi (Request-Response)

Tiêu chí Yêu cầu-Phản hồi (Đồng bộ) Hướng sự kiện (Bất đồng bộ)
Mô hình giao tiếp Client chờ phản hồi trực tiếp Producer phát sự kiện; Consumer phản ứng độc lập
Khớp nối (Coupling) Chặt — Producer biết địa chỉ Consumer Lỏng — Producer không biết Consumer [1]
Khả năng mở rộng Giới hạn bởi capacity server đích Dễ scale ngang; thêm Consumer không cần thay đổi Producer
Độ trễ (Latency) Thấp khi tải nhỏ; tăng khi tải lớn Cao hơn do buffering; ổn định hơn dưới tải lớn
Khả năng chịu lỗi Server down → pipeline thất bại Message buffered trong queue; Consumer retry [1]
Trật tự xử lý Đảm bảo ngầm định Cần FIFO queue nếu cần thứ tự
Truy vết (Debug) Dễ trace theo call stack Cần distributed tracing (X-Ray, OpenTelemetry)
Tính nhất quán Strong consistency khả thi Chủ yếu eventual consistency [3]
Phù hợp với CRUD đơn giản, cần xác nhận ngay Quy trình dài, fan-out, audit trail, high-throughput

Bảng 2.2.1: So sánh kiến trúc đồng bộ và hướng sự kiện [1][4]

Ưu Điểm EDA

  • Tách biệt (Decoupling): Producer/Consumer phát triển, triển khai, mở rộng độc lập [1]
  • Phục hồi (Resilience): Consumer ngừng hoạt động → sự kiện giữ trong queue, xử lý khi phục hồi [1]
  • Co giãn (Elasticity): Thêm Consumer instance không cần thay đổi hệ thống [4]
  • Nhật ký kiểm toán (Audit Trail): Mỗi sự kiện là bản ghi bất biến → lịch sử đầy đủ
  • Tác vụ dài hạn (Long-running Tasks): Xử lý tác vụ nặng mà không chặn người dùng

Hạn Chế EDA

  • Nhất quán cuối cùng (Eventual Consistency): Dữ liệu không nhất quán ngay; cần idempotency [3]
  • Phức tạp hạ tầng (Infrastructure Complexity): Cần thêm message broker, distributed tracing, DLQ handling [4]
  • Khó truy vết lỗi (Debug Difficulty): Luồng phi tuyến tính, khó trace end-to-end
  • Thứ tự sự kiện (Ordering): Cần FIFO queue hoặc sequence numbering [1]

2.2.3 Event Sourcing — Khái Niệm Liên Quan

Event Sourcing là pattern trong đó trạng thái thực thể được xây dựng lại từ chuỗi sự kiện đã xảy ra, thay vì lưu trạng thái hiện tại (current state). Mỗi thay đổi là sự kiện bất biến (immutable event), lưu theo thứ tự thời gian vào Event Store — cho phép truy vết lịch sử, replay, và rollback [1].

Event Sourcing có liên quan mật thiết đến EDA nhưng phức tạp hơn đáng kể: yêu cầu Event Store chuyên dụng, projection layer để xây dựng read models, và schema evolution strategy cho event versioning. Trong bối cảnh MDM quy mô đồ án tốt nghiệp, Event Sourcing thuần túy (pure Event Sourcing) là quá mức cần thiết vì:

  1. YAGNI: Quy mô 100–500 thiết bị không cần replay/rollback phức tạp
  2. PostgreSQL ACID đủ mạnh: Ghi trạng thái hiện tại (current state) với transaction đảm bảo tính toàn vẹn
  3. SNS/SQS event log cung cấp audit trail cơ bản (message retention 14 ngày) mà không cần Event Store riêng

Do đó, cách tiếp cận phù hợp là hybrid: PostgreSQL cho current state (ACID) + SNS/SQS cho event-driven side-effects (async). Nếu cần audit trail dài hạn, có thể bổ sung event archiving sau mà không thay đổi kiến trúc cốt lõi.


2.2.4 So Sánh Message Broker: SQS, RabbitMQ, Kafka

Tiêu chí AWS SQS RabbitMQ Apache Kafka
Loại Managed cloud queue Self-hosted AMQP broker Distributed streaming platform
Mô hình Point-to-point queue Queue + Exchange routing Pub-sub, topic partitions
Throughput Cao — auto scale Trung bình–cao Rất cao (triệu msg/s)
Thứ tự FIFO: theo group Theo queue (single consumer) Trong partition
Lưu trữ Tối đa 14 ngày Tới khi consumed/TTL Không giới hạn (configurable)
Replay Không Không Native support
Lambda integration Native Event Source Mapping [A5] Cần extension/polling Cần MSK + config
Vận hành Zero ops — fully managed Cần quản lý cluster Phức tạp — ZooKeeper/KRaft
Chi phí $0.40/1M msg, pay-per-use Server + vận hành Cluster + MSK licensing
DLQ Native Hỗ trợ DLQ topic
Phù hợp Serverless, AWS-native On-premise, routing phức tạp Big data, event replay

Bảng 2.2.2: So sánh message broker [1][A4][A5]

Lý Do Chọn AWS SNS + SQS

1. Fan-out với SNS: SNS Topic cho phép một sự kiện được phân phối đồng thời tới nhiều SQS queue — mỗi queue phục vụ một loại side-effect độc lập. Thêm subscriber mới không cần thay đổi publisher [A4].

2. Tích hợp Lambda native: SQS Event Source Mapping — Lambda auto trigger, không cần polling thủ công. AWS quản lý concurrency, batch size, retry, visibility timeout [A5].

3. Không cần vận hành (Zero Ops): Fully managed — không provision, upgrade, monitor server. Kafka cần ZooKeeper/KRaft cluster; RabbitMQ cần server management.

4. Phù hợp quy mô MDM: Workload MDM là CRUD + command dispatch, không phải streaming analytics. Kafka throughput triệu msg/s là quá mức cần thiết (overkill). Nguyên tắc YAGNI — SNS + SQS đủ capability [A4][A5].

5. Chi phí tối ưu: SNS: $0.50/1M notification. SQS: $0.40/1M msg. Free tier đủ cho giai đoạn phát triển.


2.2.5 EDA Trong Bối Cảnh MDM

Ưu Điểm Khi Áp Dụng EDA Cho MDM

Ưu điểm Giải thích
Tách biệt nguồn-đích Hệ thống nguồn chỉ đẩy event vào queue, không cần kết nối trực tiếp đến hệ thống đích [1]
Nhật ký kiểm toán Mỗi thay đổi = event với metadata (timestamp, actor, payload) — đáp ứng yêu cầu audit [2]
Xử lý bất đồng bộ Side-effects (lệnh thiết bị, API calls) xử lý nền; không chặn phản hồi cho người dùng [4]
Khả năng phục hồi cao Downstream ngừng hoạt động → event giữ trong SQS (14 ngày) → xử lý khi phục hồi [A5]
Cập nhật thời gian thực EDA kết hợp WebSocket/subscription cho phép push notification tức thì tới client

Thách Thức và Biện Pháp Giảm Thiểu

Nhất quán cuối cùng (Eventual Consistency)

Vogels (2009) định nghĩa: hệ thống lưu trữ đảm bảo rằng cuối cùng tất cả các truy cập sẽ trả về giá trị cập nhật gần nhất [3]. Trong MDM: sau khi lệnh được gán cho thiết bị trong cơ sở dữ liệu, các side-effect (gửi lệnh qua APNS) được xử lý bất đồng bộ — trạng thái thiết bị có thể chưa phản ánh ngay.

Biện pháp giảm thiểu:

  • Idempotent handlers: Mã sự kiện (event_id) duy nhất; handler kiểm tra trùng lặp trước khi xử lý [1]
  • PostgreSQL transactions: ACID guarantee khi ghi master data, ngăn partial write
  • Subscription push: Thông báo client ngay khi mutation hoàn tất — trước khi async side-effects kết thúc

Phức tạp truy vết lỗi (Debug Complexity)

Luồng phi tuyến tính → cần distributed tracing (AWS X-Ray) + structured logging với correlation ID xuyên suốt pipeline.

Idempotency bắt buộc

SQS = at-least-once delivery → message có thể nhận nhiều lần → Consumer phải idempotent (kiểm tra trạng thái trước khi thực thi) [A5].

Ngoại lệ: Strong Consistency

Một số thao tác cần strong consistency (ví dụ: kiểm tra trùng mã thiết bị) → xử lý đồng bộ trong PostgreSQL transaction tại tầng resolver, trước khi publish event [1].


2.2.6 Áp Dụng EDA Trong Fluxion

Lưu ý: Section này trình bày cách Fluxion áp dụng lý thuyết EDA. Chi tiết triển khai đầy đủ được trình bày tại Chương 3 — T4 — Thiết kế kiến trúc tổng thểT5 — Thiết kế Command Pipeline (Sequence Diagram).

Kiến Trúc Tổng Quan

Mô hình: GraphQL Mutation → Resolver Lambda → SQS → Worker Lambda → RDS + SNS (fan-out) → SQS → OEM Lambda → Side Effects

Cập nhật thời gian thực: AppSync Subscription (WebSocket managed)

Kiến trúc EDA Fluxion

Hình 2.2.1: Kiến trúc hướng sự kiện của hệ thống Fluxion MDM

Ánh Xạ Lý Thuyết — Thực Tiễn

Thành phần EDA Ánh xạ trong Fluxion Vai trò
Event Producer Resolver Lambda (action-resolver) Validate + enqueue sự kiện vào SQS
Event Channel SNS (fan-out) + SQS (per-consumer queue) Định tuyến + đệm sự kiện
Event Consumer Worker Lambda (action-trigger, checkin-handler) Xử lý side-effects bất đồng bộ
Event Store PostgreSQL (current state) + SQS (14-day retention) Hybrid — không dùng pure Event Sourcing
Real-time Push AppSync Subscription (WebSocket) Thông báo client tức thì

Sequence Diagram

sequenceDiagram
    participant C as 🖥️ Client
    participant Cog as ☁️ Cognito
    participant AS as ☁️ AppSync
    participant AR as λ Resolver
    participant SQS1 as ☁️ SQS (Worker)
    participant WL as λ Worker
    participant PG as 🐘 PostgreSQL
    participant SNS as ☁️ SNS (Fan-out)
    participant SQS2 as ☁️ SQS (OEM)
    participant OEM as λ OEM

    C->>Cog: authenticate (username/password)
    Cog-->>C: JWT token

    C->>AS: mutation assignAction(...) + JWT
    AS->>Cog: verify JWT
    Cog-->>AS: identity confirmed
    AS->>AR: invoke resolver (with identity context)

    AR->>AR: validate identity & permissions
    AR->>SQS1: enqueue {event_id, action_id, device_id, actor}
    AR-->>AS: mutation result
    AS-->>C: subscription push (real-time)

    Note over SQS1,WL: Bất đồng bộ — không chặn phản hồi client
    SQS1->>WL: trigger (Event Source Mapping)
    WL->>PG: INSERT action execution (transaction)
    PG-->>WL: commit OK
    WL->>SNS: publish device event

    SNS->>SQS2: fan-out to OEM subscriber
    SQS2->>OEM: trigger (Event Source Mapping)
    OEM->>OEM: idempotency check (event_id)
    OEM->>OEM: send command to device via APNS
    OEM-->>SQS2: ack

Hình 2.2.2: Sequence diagram luồng sự kiện trong Fluxion

Xử Lý Lỗi

Tình huống Hành vi
Resolver Lambda lỗi AppSync trả GraphQL error → client nhận thông báo lỗi; không publish SQS
Worker Lambda lỗi SQS visibility timeout → message trở lại queue → retry tự động [A5]
SNS publish thất bại Worker retry; sau max retries → message vào DLQ
OEM Lambda timeout SQS visibility timeout hết → retry; sau 3 lần → DLQ → CloudWatch alarm
Dịch vụ bên ngoài không phản hồi Lambda exception → SQS retry với exponential backoff [A5]

Bảng 2.2.3: Kịch bản lỗi và hành vi xử lý trong pipeline EDA


2.2.7 Tổng Kết

Kiến trúc hướng sự kiện (EDA) giải quyết ba thách thức cốt lõi trong hệ thống MDM hiện đại: tách biệt giữa các thành phần phân tán, phục hồi khi có lỗi xảy ra, và co giãn theo số lượng thiết bị — đây là những yêu cầu phi chức năng mà kiến trúc đồng bộ truyền thống (request-response) khó đáp ứng khi quy mô tăng [1][4].

Sự kết hợp hai mô hình phân phối — point-to-point queue (SQS) cho xử lý tuần tự và publish-subscribe topic (SNS) cho fan-out — tạo ra cơ chế linh hoạt: mỗi sự kiện vừa được xử lý đúng một lần bởi worker, vừa được phân phối đồng thời tới nhiều consumer downstream [A4][A5]. Đây là pattern phổ biến trong hệ thống serverless trên AWS.

Hạn chế chính — eventual consistency — được chấp nhận trong bối cảnh MDM: kết quả mutation được xác nhận ngay lập tức cho client qua subscription, còn việc thực thi lệnh trên thiết bị vốn là tác vụ bất đồng bộ (phụ thuộc APNS và trạng thái mạng thiết bị). Idempotency, DLQ retry, và PostgreSQL ACID cho master data là ba biện pháp đảm bảo tính nhất quán cuối cùng [3].


Tài Liệu Tham Khảo

[1] Hohpe, G. & Woolf, B. (2003). Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions. Addison-Wesley Professional. https://www.enterpriseintegrationpatterns.com

[2] NIST. (2023). Guidelines for Managing the Security of Mobile Devices in the Enterprise (SP 800-124 Rev. 2). National Institute of Standards and Technology. https://csrc.nist.gov/pubs/sp/800/124/r2/final

[3] Vogels, W. (2009). Eventually Consistent. Communications of the ACM, 52(1), 40–44. https://dl.acm.org/doi/10.1145/1435417.1435432

[4] Michelson, B. M. (2006). Event-Driven Architecture Overview. Patricia Seybold Group. https://www.omg.org/soa/Uploaded%20Docs/EDA/bda2-2-06cc.pdf

[5] Newman, S. (2015). Building Microservices: Designing Fine-Grained Systems (Ch. 4: Integration). O'Reilly Media. https://www.oreilly.com/library/view/building-microservices/9781491950340/

[A1] AWS. (2024). What is AWS AppSync? AWS AppSync Developer Guide. https://docs.aws.amazon.com/appsync/latest/devguide/what-is-appsync.html

[A2] AWS. (2024). Real-time data with AWS AppSync subscriptions. AWS AppSync Developer Guide. https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html

[A3] AWS. (2024). What is Amazon Cognito? Amazon Cognito Developer Guide. https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html

[A4] AWS. (2024). What is Amazon SNS? Amazon SNS Developer Guide. https://docs.aws.amazon.com/sns/latest/dg/welcome.html

[A5] AWS. (2024). Using Lambda with Amazon SQS. AWS Lambda Developer Guide. https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html