Bỏ qua để đến nội dung

Tích hợp ứng dụng trên Cloud

Khi bạn triển khai nhiều ứng dụng trên AWS, chúng hầu như không bao giờ hoạt động độc lập hoàn toàn — chúng cần “nói chuyện” với nhau. Ví dụ, một hệ thống bán hàng trực tuyến có thể gồm: dịch vụ Đặt hàng (Buying Service), dịch vụ Giao hàng (Shipping Service), dịch vụ chống gian lận (Fraud Service), dịch vụ gửi email… Câu hỏi đặt ra là: các dịch vụ này nên giao tiếp với nhau theo cách nào?

Có hai mô hình giao tiếp chính giữa các ứng dụng:

  • Giao tiếp đồng bộ (Synchronous communication): ứng dụng A gọi trực tiếp ứng dụng B và chờ B xử lý xong rồi trả kết quả về. Ví dụ: Buying Service gọi trực tiếp API của Shipping Service để yêu cầu tạo đơn giao hàng, và phải đợi Shipping Service trả lời “đã tạo xong” mới tiếp tục.
  • Giao tiếp bất đồng bộ / theo sự kiện (Asynchronous / Event-based communication): ứng dụng A không gọi trực tiếp ứng dụng B, mà gửi một “thông điệp” (message) vào một hàng đợi (queue) trung gian. Ứng dụng B sẽ tự lấy thông điệp đó ra khi nó sẵn sàng và xử lý. Ví dụ: Buying Service → Queue → Shipping Service.

Hãy tưởng tượng giao tiếp đồng bộ như việc bạn gọi điện thoại trực tiếp cho một người bạn để nhờ việc: nếu người đó đang bận (không nghe máy, đường truyền quá tải), bạn phải chờ hoặc gọi lại — công việc của bạn bị chặn lại (blocked). Giao tiếp bất đồng bộ giống như việc bạn gửi một tin nhắn hoặc email: bạn cứ gửi, và người nhận sẽ đọc và xử lý khi họ có thời gian, không làm bạn phải chờ đợi ngay lúc đó.

Vấn đề của giao tiếp đồng bộ là nó rất dễ “vỡ trận” khi có sự tăng tải bất thường (traffic spike). Ví dụ điển hình: bình thường hệ thống của bạn cần mã hóa (encode) 10 video mỗi giờ, nhưng bất ngờ có một sự kiện khiến số lượng video cần xử lý tăng vọt lên 1000 video. Nếu dịch vụ xử lý video được gọi trực tiếp (đồng bộ) bởi dịch vụ upload, thì dịch vụ upload sẽ bị “nghẽn” theo — người dùng phải chờ rất lâu, hoặc hệ thống bị lỗi timeout, thậm chí sập cả hai dịch vụ.

Giải pháp cho vấn đề này là tách rời (decouple) các ứng dụng khỏi nhau bằng các dịch vụ trung gian chuyên dụng của AWS, giúp mỗi thành phần có thể co giãn quy mô (scale) một cách độc lập với các thành phần khác. Ba dịch vụ chính cho việc này là:

  • Amazon SQS — mô hình hàng đợi (queue model).
  • Amazon SNS — mô hình xuất bản/đăng ký (publish/subscribe model).
  • Amazon Kinesis — mô hình truyền dữ liệu theo luồng thời gian thực (real-time data streaming model).

SQS (Simple Queue Service) là dịch vụ hàng đợi thông điệp (message queue) hoàn toàn được quản lý bởi AWS. Để hiểu SQS, trước tiên hãy hiểu “hàng đợi” (queue) là gì trong ngữ cảnh phần mềm: đó là một cấu trúc dữ liệu giống như một dòng người đang xếp hàng chờ tại quầy — người vào trước sẽ đứng ở đầu hàng, và người đến sau xếp vào cuối hàng.

Trong SQS có hai vai trò chính:

  • Producer (người sản xuất/gửi thông điệp): là ứng dụng gửi các message vào hàng đợi SQS. Producer có thể gửi rất nhiều message cùng lúc, không cần biết ai sẽ xử lý chúng.
  • Consumer (người tiêu thụ/xử lý thông điệp): là ứng dụng liên tục “polling” (chủ động hỏi/kiểm tra) hàng đợi để lấy các message ra và xử lý.

Điểm mấu chốt là Producer và Consumer hoàn toàn không biết đến sự tồn tại của nhau — chúng chỉ biết đến hàng đợi SQS ở giữa. Điều này chính là bản chất của việc “tách rời” (decoupling): nếu Consumer đang xử lý chậm hoặc tạm thời offline, các message vẫn an toàn nằm trong hàng đợi chờ được xử lý, Producer vẫn tiếp tục gửi message bình thường mà không bị ảnh hưởng.

SQS Standard Queue là loại hàng đợi cơ bản và cũng là dịch vụ tích hợp lâu đời nhất của AWS (đã tồn tại hơn 10 năm) — điều này cho thấy đây là một dịch vụ rất ổn định, được kiểm chứng qua thời gian và được sử dụng rộng rãi trong ngành.

Các đặc điểm quan trọng của SQS Standard Queue:

  • Fully managed (~serverless): bạn không cần quản lý server, không cần lo về việc mở rộng hạ tầng — AWS tự vận hành toàn bộ phía sau.
  • Mục đích: dùng để tách rời (decouple) các ứng dụng với nhau.
  • Khả năng co giãn (scale): từ 1 message/giây cho đến hàng chục nghìn message mỗi giây — gần như không có giới hạn thực tế cho việc mở rộng.
  • Thời gian lưu trữ message (retention): mặc định là 4 ngày, có thể cấu hình tối đa lên đến 14 ngày. Sau thời gian này, nếu chưa có consumer nào đọc, message sẽ tự bị xóa.
  • Không giới hạn số lượng message có thể tồn tại trong hàng đợi cùng lúc.
  • Message bị xóa sau khi được đọc bởi consumer (sau khi consumer xác nhận đã xử lý xong — gọi là “delete” message khỏi hàng đợi).
  • Độ trễ (latency) rất thấp: dưới 10 milli-giây (ms) cho cả việc gửi (publish) và nhận (receive) message.
  • Nhiều consumer có thể chia nhau xử lý: các consumer chia sẻ công việc đọc message và có thể co giãn theo chiều ngang (horizontal scaling) — tức là bạn có thể thêm nhiều consumer (nhiều EC2 instance chẳng hạn) để xử lý message nhanh hơn khi hàng đợi có nhiều việc.
Đặc điểm Giá trị
Retention mặc định 4 ngày
Retention tối đa 14 ngày
Độ trễ publish/receive Dưới 10ms
Thông lượng Từ 1 đến hàng chục nghìn message/giây
Giới hạn số message trong queue Không giới hạn

Một ví dụ kinh điển thể hiện rõ giá trị của SQS: hệ thống có một tầng Web Server (chạy trong một Auto Scaling Group gồm các EC2 Instance) nhận các yêu cầu từ người dùng — ví dụ yêu cầu xử lý (encode) video vừa tải lên. Thay vì Web Server tự xử lý video ngay (rất tốn tài nguyên và mất thời gian), nó chỉ đơn giản đẩy (PUT) một message vào SQS Queue mô tả công việc cần làm, rồi trả lời ngay cho người dùng là “đã nhận yêu cầu, đang xử lý”.

Sau đó, một tầng khác — Auto Scaling Group riêng biệt gồm các EC2 Instance chuyên xử lý video (Video Processing) — sẽ tự động co giãn số lượng instance dựa trên độ sâu (depth = số lượng message đang chờ) của hàng đợi, và liên tục kéo (pull) công việc từ hàng đợi ra để xử lý.

Lợi ích của mô hình này:

  • Tầng Web Server và tầng Video Processing hoàn toàn độc lập, có thể co giãn (scale up/down) theo tốc độ và nhu cầu riêng của mình.
  • Nếu lượng video cần xử lý tăng đột biến, hàng đợi SQS sẽ “hấp thụ” cú sốc đó — các message chỉ đơn giản chờ trong hàng đợi lâu hơn một chút, hệ thống Web Server phía trước không bị ảnh hưởng hay sập.
  • Auto Scaling Group của tầng xử lý video có thể tự thêm instance khi hàng đợi có nhiều việc, và giảm instance khi hàng đợi trống — tối ưu chi phí.

SQS Standard Queue có một hạn chế: nó không đảm bảo thứ tự các message được xử lý (message có thể đến trước nhưng lại được consumer xử lý sau, do tính chất phân tán và khả năng scale cao). Với đa số ứng dụng điều này không sao, nhưng có những trường hợp thứ tự lại rất quan trọng.

FIFO là viết tắt của “First In First Out” — nghĩa là thông điệp nào được gửi vào hàng đợi trước sẽ được lấy ra và xử lý trước, giống như việc xếp hàng: ai đến trước, được phục vụ trước.

Ví dụ: nếu Producer gửi các message theo thứ tự 1, 2, 3, 4 vào một FIFO Queue, thì Consumer khi polling/nhận message sẽ luôn nhận được chúng đúng theo thứ tự 1, 2, 3, 4 — không bị xáo trộn. Điều này đảm bảo rằng các message được xử lý theo đúng trình tự mà chúng được tạo ra.

Đối với kỳ thi CLF-C02, bạn chỉ cần nhớ một câu ngắn gọn: Kinesis = giải pháp truyền dữ liệu lớn theo thời gian thực (real-time big data streaming). Đây là dịch vụ được quản lý hoàn toàn (managed service), dùng để thu thập (collect), xử lý (process) và phân tích (analyze) dữ liệu dạng luồng (streaming data) theo thời gian thực, ở bất kỳ quy mô nào — từ vài bản ghi mỗi giây đến hàng trăm nghìn nguồn gửi dữ liệu liên tục.

Khác với SQS (dùng cho các message rời rạc, mỗi message xử lý một lần và bị xóa sau đó), Kinesis phù hợp với các luồng dữ liệu liên tục, khối lượng lớn, cần được xử lý và phân tích gần như ngay lập tức khi dữ liệu vừa sinh ra — ví dụ dữ liệu click chuột trên website, dữ liệu từ thiết bị IoT, hoặc log & metrics hệ thống.

Trong hệ sinh thái Kinesis có nhiều thành phần, nhưng hai cái quan trọng để biết ở mức tổng quan là:

  • Amazon Kinesis Data Streams: cho phép nạp (ingest) dữ liệu độ trễ thấp (low latency) ở quy mô lớn, từ hàng trăm nghìn nguồn dữ liệu khác nhau cùng lúc.
  • Amazon Data Firehose: lấy dữ liệu từ Kinesis Data Streams và tự động nạp (load) nó vào các nơi lưu trữ/phân tích đích như Amazon S3, Amazon Redshift, Amazon OpenSearch, v.v.

Luồng dữ liệu tổng quát của Kinesis diễn ra như sau: các nguồn dữ liệu (Click Streams từ website, thiết bị IoT, Metrics & Logs hệ thống) → chảy vào Amazon Kinesis Data Streams → được Amazon Data Firehose lấy ra → đưa tới các đích lưu trữ/phân tích như Amazon S3, Amazon Redshift…

SQS giải quyết bài toán “một message được xử lý bởi một trong nhiều consumer” (mỗi message chỉ được một consumer xử lý và xóa). Nhưng có một bài toán khác: điều gì xảy ra nếu bạn muốn một message được gửi đến NHIỀU người nhận cùng lúc, và mỗi người nhận đều phải nhận được đầy đủ toàn bộ message đó?

Đây chính là bài toán mà Amazon SNS (Simple Notification Service) giải quyết, dựa trên mô hình Publish/Subscribe (Pub/Sub) — nghĩa là “xuất bản và đăng ký”.

Ví dụ: dịch vụ Buying Service khi có đơn hàng mới sẽ “publish” (xuất bản/gửi) một message vào một SNS Topic duy nhất. Topic này đã có sẵn nhiều “subscriber” (người đăng ký nhận thông báo) đăng ký lắng nghe, ví dụ: Shipping Service, dịch vụ gửi Email thông báo, Fraud Service (dịch vụ chống gian lận). Ngay khi message được publish vào topic, TẤT CẢ các subscriber này đều nhận được đầy đủ nội dung message đó cùng lúc.

So sánh với cách làm truyền thống là “Direct integration” — Buying Service phải tự gọi trực tiếp lần lượt đến từng dịch vụ (Shipping Service, Email Service, Fraud Service…): cách này khiến Buying Service phải biết và quản lý kết nối tới từng dịch vụ, rất cồng kềnh và khó mở rộng khi có thêm subscriber mới. Với SNS, Buying Service chỉ cần biết đến MỘT topic duy nhất, việc thêm/bớt subscriber không ảnh hưởng gì đến Buying Service.

Một điểm rất thường gặp trong thực tế và trong đề thi là mô hình “SNS + SQS Fan-out”: SNS Topic có thể “fan out” (phân tán) message ra thành nhiều SQS Queue riêng biệt cho mỗi subscriber, thay vì gửi trực tiếp đến ứng dụng của subscriber. Lý do là vì SNS không lưu trữ lại message (không có retention) — nếu subscriber tạm thời offline khi message được gửi, nó sẽ mất message đó vĩnh viễn. Nhưng nếu subscriber là một SQS Queue, message sẽ được lưu an toàn trong queue đó cho đến khi được xử lý, đảm bảo tính durable (bền vững, không mất dữ liệu).

Một số thông tin chi tiết khác về SNS:

  • “Event publisher” chỉ cần gửi message đến MỘT SNS topic duy nhất.
  • Có thể có rất nhiều “event subscriber” lắng nghe thông báo từ topic đó — mỗi subscriber nhận được TẤT CẢ các message được gửi vào topic.
  • Giới hạn: tối đa 12.500.000 lượt đăng ký (subscriptions) cho mỗi topic, và tối đa 100.000 topic.
  • Các loại subscriber được hỗ trợ: SQS, AWS Lambda, Amazon Data Firehose, HTTP(S) Endpoint, SMS & thông báo di động (Mobile Notifications), và Email.
Tiêu chí Amazon SQS Amazon SNS
Mô hình Hàng đợi (Queue) – Point to point Xuất bản/Đăng ký (Pub/Sub)
Số người nhận mỗi message 1 consumer (rồi bị xóa khỏi queue) Nhiều subscriber (mỗi subscriber nhận đủ)
Lưu trữ message (retention) Có, tối đa 14 ngày Không có retention
Đảm bảo thứ tự Có (bản FIFO) Có (bản FIFO topic)
Vai trò điển hình Phân phối công việc, tách rời tầng ứng dụng Thông báo/phát tán một sự kiện đến nhiều bên

SQS và SNS là các dịch vụ “cloud-native” — nghĩa là chúng được AWS thiết kế riêng, sử dụng các giao thức (protocol) độc quyền (proprietary) của AWS thông qua API riêng. Điều này rất tối ưu cho các ứng dụng được xây dựng mới trên cloud, nhưng lại là một vấn đề đối với các ứng dụng cũ (legacy) đang chạy on-premises (tại trung tâm dữ liệu riêng của doanh nghiệp).

Các ứng dụng truyền thống đó thường sử dụng các giao thức message broker mở (open protocol) như MQTT, AMQP, STOMP, OpenWire, WSS — đây là các chuẩn giao tiếp được nhiều hệ thống message broker phổ biến như ActiveMQ, RabbitMQ hỗ trợ từ trước khi có cloud.

Khi một doanh nghiệp muốn di trú (migrate) ứng dụng loại này lên AWS, thay vì phải viết lại (re-engineer) toàn bộ ứng dụng để chuyển sang dùng SQS/SNS (tốn thời gian, chi phí, rủi ro), AWS cung cấp Amazon MQ — một dịch vụ message broker được quản lý (managed message broker service), hỗ trợ trực tiếp các giao thức mở nói trên, giúp ứng dụng gần như không cần sửa đổi gì khi chuyển lên cloud.

Một vài điểm khác biệt quan trọng của Amazon MQ so với SQS/SNS:

  • Amazon MQ không co giãn (scale) mạnh như SQS/SNS — vì nó chạy trên các server thực (không phải mô hình serverless hoàn toàn).
  • Amazon MQ có thể chạy ở chế độ Multi-AZ với khả năng chuyển đổi dự phòng (failover) để đảm bảo tính sẵn sàng cao.
  • Amazon MQ hỗ trợ CẢ hai tính năng hàng đợi (queue, tương tự SQS) VÀ tính năng topic (tương tự SNS) trong cùng một dịch vụ.
  • Giao tiếp đồng bộ vs bất đồng bộ: gọi trực tiếp dễ vỡ trận khi tải tăng đột biến; nên dùng hàng đợi/topic trung gian để tách rời (decouple) ứng dụng.
  • Amazon SQS: dịch vụ hàng đợi, nhiều producer gửi vào, nhiều consumer chia nhau đọc và xóa, message lưu tối đa 14 ngày, dùng để tách rời các tầng ứng dụng.
  • SQS FIFO Queue: đảm bảo message được xử lý đúng thứ tự đã gửi (First In First Out).
  • Amazon Kinesis: giải pháp streaming dữ liệu lớn theo thời gian thực, gồm Kinesis Data Streams (ingest) và Amazon Data Firehose (load vào S3, Redshift…).
  • Amazon SNS: dịch vụ thông báo theo mô hình Pub/Sub, một message publish vào topic được gửi đến tất cả subscriber, không có retention, thường kết hợp “fan-out” với SQS để đảm bảo không mất dữ liệu.
  • Amazon MQ: managed message broker cho ActiveMQ/RabbitMQ, hỗ trợ giao thức mở (MQTT, AMQP…), phù hợp khi di trú ứng dụng cũ lên cloud mà không muốn viết lại code.