📨 SQS, SNS, EventBridge và Step Functions: chọn dịch vụ tích hợp

Mục tiêu bài học

  • Phân biệt SQS, SNS, EventBridge và Step Functions theo kiểu giao tiếp mà mỗi dịch vụ giải quyết, không học thuộc lòng tính năng rời rạc.
  • Chọn đúng dịch vụ cho bốn tình huống thi hay gặp: decoupling, fan-out, routing theo sự kiện, điều phối workflow nhiều bước.
  • Nắm các tham số bị hỏi nhiều nhất: visibility timeout, retention, DLQ, FIFO, long polling, Standard so với Express workflow.
  • Nhận diện bẫy thường gặp để loại đáp án nhiễu trong vòng 30 giây.

Ôn nhanh

Bài trước bạn đã học CloudFormation: stack là đơn vị triển khai, change set là bản xem trước thay đổi trước khi apply. Nhắc lại một ý nối sang bài này: các resource messaging đều khai báo được trong template (AWS::SQS::Queue, AWS::SNS::Topic, AWS::StepFunctions::StateMachine), nên đề thi hay hỏi cả "chọn dịch vụ nào" lẫn "khai báo thuộc tính gì".

Lý thuyết

Bốn dịch vụ, bốn câu hỏi khác nhau

Dịch vụ Kiểu giao tiếp Ai nhận message? Câu hỏi chọn nhanh
SQS Queue, point-to-point, kéo (poll) Một consumer hoặc nhiều consumer cạnh tranh Cần buffer, giảm tải, retry?
SNS Pub/sub, push Nhiều subscriber cùng lúc Một message tới nhiều nơi?
EventBridge Event bus, routing theo rule Nhiều target, lọc theo nội dung Định tuyến sự kiện từ nhiều nguồn?
Step Functions Orchestration, state machine Chính workflow điều khiển Nhiều bước, có nhánh, chờ, retry?

SQS: hàng đợi và decoupling

  • Standard: giao at-least-once, thứ tự không đảm bảo, throughput gần như không giới hạn. Consumer phải idempotent.
  • FIFO: giữ thứ tự trong từng MessageGroupId, có dedup bằng MessageDeduplicationId, throughput thấp hơn Standard.
  • Visibility timeout: sau khi consumer nhận, message bị ẩn; hết thời gian mà chưa DeleteMessage thì message hiện lại và bị xử lý lần hai. Mặc định 30 giây, tối đa 12 giờ.
  • Retention: mặc định 4 ngày, tối đa 14 ngày. Message tối đa 256 KB.
  • Long polling (WaitTimeSeconds tới 20) giảm số lần poll rỗng, tiết kiệm chi phí so với short polling.
  • DLQ gắn qua redrive policy với maxReceiveCount, dùng cho poison message. DLQ phải cùng loại queue.
  • Với Lambda, SQS là event source mapping: Lambda tự poll theo batch, có batchSize, maximumBatchingWindow, và ReportBatchItemFailures để chỉ retry phần lỗi.

SNS: fan-out và push

  • Topic nhận publish rồi đẩy tới nhiều subscriber: SQS, Lambda, HTTP/S, email, SMS, mobile push.
  • Fan-out chuẩn: SNS topic đẩy vào nhiều SQS queue, mỗi queue một consumer, retry và DLQ độc lập.
  • Subscription filter policy (JSON) để chỉ đẩy message khớp thuộc tính, giảm việc lọc ở consumer.
  • SNS không lưu message chờ subscriber. Nếu subscriber chết, message có thể mất. Đây chính là lý do fan-out phải dùng SQS làm đích.
  • SNS FIFO topic chỉ fan-out được tới SQS FIFO queue.

EventBridge: routing theo sự kiện

  • Event bus gồm default, custom và partner. Rule so khớp event pattern rồi đẩy tới target (Lambda, SQS, Step Functions, API destination...).
  • Nguồn sự kiện rộng: AWS service events, SaaS partner, ứng dụng tự phát sinh event.
  • Schedule rule (rate/cron) thay cho cron job tự viết.
  • Archive and replay: phát lại sự kiện trong quá khứ, tính năng hay xuất hiện trong câu hỏi khó.
  • So với SNS: EventBridge lọc theo nội dung phức tạp hơn và nhiều nguồn hơn; SNS đơn giản hơn, độ trễ thấp, fan-out khối lượng lớn.

Step Functions: điều phối workflow

  • State machine định nghĩa bằng Amazon States Language (JSON).
  • Standard: chạy tới 1 năm, lịch sử thực thi đầy đủ, exactly-once. Express: tối đa 5 phút, throughput cao, giá rẻ hơn, at-least-once, không có lịch sử đầy đủ.
  • State hay hỏi: Task, Choice, Parallel, Map, Wait, Pass, Succeed, Fail.
  • Retry có MaxAttempts, BackoffRate; Catch chuyển sang nhánh xử lý lỗi.
  • Callback pattern với task token cho bước chờ người duyệt hoặc job dài.
flowchart TD
  Start["❓ Yêu cầu tích hợp"] --> Q1{"Nhiều bước, có nhánh, chờ, retry?"}
  Q1 -->|Có| SF["🔀 Step Functions"]
  Q1 -->|Không| Q2{"Một message tới nhiều consumer?"}
  Q2 -->|Có| Q3{"Lọc theo nội dung, nhiều nguồn sự kiện?"}
  Q3 -->|Có| EB["📡 EventBridge"]
  Q3 -->|Không| SNS["📢 SNS fan-out"]
  Q2 -->|Không| Q4{"Cần buffer và retry độc lập?"}
  Q4 -->|Có| SQS["📥 SQS"]
  Q4 -->|Không| Direct["Gọi trực tiếp service"]

Ví dụ từng bước

Ví dụ 1: fan-out khi upload file. Đề bài: mỗi file upload lên S3 phải chạy ba xử lý (tạo thumbnail, trích text, ghi audit), mỗi xử lý retry độc lập và không được mất message.

1. S3 phát event tới một SNS topic (hoặc một EventBridge rule).
2. Ba SQS queue subscribe topic, mỗi queue gắn filter policy riêng.
3. Mỗi Lambda consume đúng một queue qua event source mapping.
4. Gắn DLQ cho từng queue với `maxReceiveCount = 3`.
5. Bật `ReportBatchItemFailures` để chỉ retry message lỗi trong batch.

Lý do chọn: SNS đẩy song song tới nhiều nơi, SQS giữ message khi consumer chết. Đây là pattern==SNS fan-out + SQS buffer==.

Ví dụ 2: workflow đặt hàng. Validate, trừ kho, thanh toán, gửi mail, cập nhật DB, nếu thanh toán lỗi thì hoàn kho.

1. State `Task` gọi Lambda validate, có `Retry` với `BackoffRate` 2.0.
2. State `Task` gọi thanh toán, `Catch` chuyển sang state hoàn kho.
3. State `Choice` rẽ nhánh theo kết quả.
4. State `Parallel` chạy song song gửi mail và cập nhật DynamoDB.
5. Kết thúc bằng `Succeed`, lỗi không cứu được thì `Fail`.

Đây là lúc Step Functions thắng SQS: có nhánh, có bù trừ, có trạng thái từng bước để debug.

Ví dụ 3: câu hỏi bẫy về message lớn. Đề cho message 1 MB. Đáp án đúng là claim check pattern: nội dung thật lưu vào S3, message qua SQS chỉ chứa pointer cùng metadata, consumer đọc S3 rồi xử lý.

Thảo luận và suy ngẫm

  1. Trong hệ thống của bạn, chỗ nào đang gọi trực tiếp service khác và nên đổi sang SQS? Điều gì sẽ hỏng nếu service đích chết 10 phút?
  2. Khi nào bạn chọn EventBridge thay cho SNS dù cả hai đều là pub/sub?
  3. Nếu một workflow có bước chờ người duyệt ba ngày, Standard hay Express workflow phù hợp? Vì sao?

Góc chuyên gia

  • Bẫy kinh điển: nhầm visibility timeout với delay queue. Delay queue hoãn lần giao đầu tiên (tối đa 15 phút); visibility timeout áp dụng sau khi đã có consumer nhận.
  • DLQ phải cùng loại: FIFO queue cần FIFO DLQ. Đề rất hay gài chi tiết này.
  • SNS không bền: subscriber không khả dụng thì message có thể mất. Nếu đề nhấn "không được mất message", phải có SQS ở giữa.
  • EventBridge là at-least-once: target có thể nhận trùng, nên vẫn cần idempotent như SQS.
  • Express workflow không phù hợp cho job dài, không có lịch sử thực thi đầy đủ và không hỗ trợ các pattern .sync của Standard.
  • Rule of thumb khi vào phòng thi: cần buffer thì SQS, cần fan-out thì SNS + SQS, cần lọc sự kiện từ nhiều nguồn thì EventBridge, cần nhiều bước có nhánh và retry thì Step Functions.

[!WARNING] Đừng chọn Step Functions chỉ vì "workflow có hai bước". Nếu yêu cầu chỉ là decouple hai service và retry khi lỗi, SQS là đáp án rẻ và đúng hơn.

SQS giữ message tối đa {{c1::14 ngày}}, mặc định là 4 ngày.
Sau khi consumer nhận message, message bị ẩn trong khoảng {{c2::visibility timeout}}; hết thời gian đó mà chưa delete thì message hiện lại.
Để nhiều consumer cùng nhận một sự kiện và xử lý độc lập, ta dùng pattern {{c3::fan-out}} với SNS đẩy vào nhiều SQS queue.
Để định tuyến sự kiện theo nội dung từ nhiều nguồn khác nhau, dịch vụ phù hợp là {{c4::EventBridge}}.
Step Functions {{c5::Express}} workflow chỉ chạy tối đa 5 phút và không có lịch sử thực thi đầy đủ như Standard.
Message vượt quá 256 KB nên xử lý bằng {{c6::claim check pattern}}: lưu nội dung vào S3 và gửi pointer qua SQS.
[
  { "front": "SQS Standard đảm bảo gì về thứ tự và số lần giao message?", "back": "At-least-once, thứ tự không đảm bảo, nên consumer phải idempotent." },
  { "front": "Visibility timeout của SQS mặc định và tối đa là bao nhiêu?", "back": "Mặc định 30 giây, tối đa 12 giờ." },
  { "front": "SQS giữ message tối đa bao lâu?", "back": "Mặc định 4 ngày, tối đa 14 ngày." },
  { "front": "Kích thước message tối đa của SQS và SNS?", "back": "256 KB." },
  { "front": "Long polling đặt WaitTimeSeconds tối đa bao nhiêu và để làm gì?", "back": "20 giây; giảm số lần poll rỗng và chi phí so với short polling." },
  { "front": "DLQ của một FIFO queue phải là loại queue nào?", "back": "FIFO queue, DLQ phải cùng loại với queue nguồn." },
  { "front": "Pattern fan-out chuẩn trên AWS gồm những thành phần nào?", "back": "Một SNS topic đẩy tới nhiều SQS queue, mỗi queue có consumer và DLQ riêng." },
  { "front": "SNS có lưu message khi subscriber không khả dụng không?", "back": "Không, message có thể mất; dùng SQS làm subscriber để có buffer." },
  { "front": "SNS FIFO topic chỉ fan-out được tới đâu?", "back": "Chỉ tới SQS FIFO queue." },
  { "front": "EventBridge dùng cơ chế nào để lọc sự kiện?", "back": "Rule so khớp với event pattern dạng JSON." },
  { "front": "Tính năng nào của EventBridge cho phép phát lại sự kiện trong quá khứ?", "back": "Archive and replay." },
  { "front": "Phân biệt Standard và Express workflow của Step Functions?", "back": "Standard chạy tới 1 năm, lịch sử đầy đủ, exactly-once; Express tối đa 5 phút, throughput cao, at-least-once." },
  { "front": "State nào trong Step Functions rẽ nhánh theo điều kiện?", "back": "Choice state." },
  { "front": "Xử lý message lớn hơn 256 KB bằng cách nào?", "back": "Claim check pattern: nội dung lưu trong S3, message chỉ chứa pointer." }
]

Tóm tắt và bước tiếp theo

Bốn câu chốt: SQS để decouple và buffer, SNS để fan-out push tới nhiều nơi, EventBridge để định tuyến sự kiện theo nội dung từ nhiều nguồn, Step Functions để điều phối workflow nhiều bước có nhánh và retry. Kèm theo: visibility timeout, retention 14 ngày, DLQ cùng loại queue, Standard so với Express.

Bài tiếp theo là Checkpoint: Triển khai và tích hợp, nơi bạn sẽ ghép CodePipeline, CloudFormation và bốn dịch vụ messaging này vào một bộ câu hỏi tình huống theo đúng kiểu đề DVA-C02.