Kiến trúc Serverless: Xử lý công việc không đồng bộ với SQS và Lambda Function

Bài viết sẽ chỉ cho bạn cách xử lý một khối lượng lớn công việc không đồng bộ bằng kiến trúc Serverless. Các trường hợp ứng dụng có thể là: Gửi email với số lượng lớn, xử lý video sau khi được tải lên, hoặc phân tích hành vi người dùng…

Chúng ta sử dụng SQS như một hàng chờ, hàng chờ này sẽ được dùng để tách rời các service trong mô hình microservice của bạn. Bạn sẽ thấy được cách tôi triển khi mô hình microservice sử dụng Lambda Function.

Giới thiệu SQS

Cách tốt nhất để xây dựng một hệ thống có khả năng mở rộng và tối ưu hiệu suất trên hạ tầng của AWS là tách rời các dịch vụ thành mô hình microservice, từ đó ta có thể áp dụng các tùy chọn sau (hoặc cả 2):

  • ELB (Elastic Load Balancing) cho việc xử lý đồng bộ các yêu cầu: Các ứng dụng web sẽ xử lý và trả lời các yêu cầu https được gửi từ trình duyệt, client.
  • SQS queue để xử lý các công việc không đồng bộ: gửi số lượng lớn email, xử lý video sau khi tải lên hoặc phân tích hành vi của người dùng.

Amazon Simple Queue Service (SQS)  là một dịch vụ hàng đợi, lưu trữ và quản lý thông điệp. SQS cung cấp dịch vụ hàng đợi lưu trữ thông tin phân tán có khả năng chịu lỗi và mở rộng: Đơn giản để sử dụng nhưng rất mạnh mẽ.

Hình ảnh dưới đây cho thấy một kiến trúc điển hình có sử dụng SQS. Một (hoặc nhiều) dịch vụ (Producer) gửi các tác vụ (hay gọi là bản tin) tới hàng đợi SQS. Một (hoặc nhiều) dịch vụ(Consumer) khác sẽ đọc các bản tin này để xử lý các yêu cầu cụ thể theo bài toán thực tế.

Push-Pull: Amazon SQS – http://fbrnc.net/blog/2016/03/messaging-on-aws

Số lượng Consumer có thể được thu nhỏ dựa trên số lượng tác vụ trong hàng đợi. Vì các tác vụ được lưu trữ và quản lý một các lâu dài trong SQS, nên rất dễ dàng để xây dựng một hệ thống tự động phục hồi nếu một consumer bị lỗi, chúng ta sẽ không bị mất một bản ghi nào.

SQS cung cấp REST API, do đó, có rất nhiều các để tích hợp vào Producer hay Consumer: Ứng dụng di động, client-side ứng dụng web, một ứng dụng chạy trên máy chủ EC2 hoặc AWS Lambda Function.

Giới thiệu Lambda Function

Amazon công bố AWS Lambda vào tháng 11 năm 2014. Kể từ đó, Serverless đã trở thành một trong những chủ đề nóng nhất trong thị trường đám mây.

AWS Lambda cung cấp:

  • Khả năng mở rộng và tối ưu tính toán.
  • Cho phép bạn thiết lập triển khai tự động với sự hỗ trợ của các dịch vụ CD(continuous Development).
  • Dễ dàng quản lý và không cần bảo trì.

AWS Lambda hỗ trợ các ngôn ngữ lập trình Node.js, Java, Python, .NET Core và Go. Bạn chỉ cần tải mã nguồn của mình lên S3. Sau đó bạn có thể thực thi chức năng của một function bằng cách gọi REST API (kết hợp với API Gateway) hoặc sử dụng một số dịch vụ có thể tích hợp khác: Kinesis, S3, DynamoDB, CloudTrail…

Thật may cho bạn, tại thời điểm của bài viết này, chúng ta có thể tích hợp trực tiếp SQS và Lambda (trước tháng 6 năm 2018 thì không, chúng ta phải dùng một cách khác – CloudWatch Event Rule)

Tích hợp Lambda và SQS

Hình ảnh dưới đây cho thấy các thành phần cần thiết để đọc và xử lý tin nhắn từ dịch vụ SQS.

Chúng ta sẽ dùng tới CloudFormation để thiết kế cơ sở hạ tầng. CloudFormation làm một công cụ thiết kế, xây dựng cơ sở hạ tầng bằng code 🙂 .

Thiết lập SQS queue

Đầu tiên, chúng ta cần chuẩn bị một SQS queue, đoạn code dưới đây sẽ mô tả queue của chúng ta:

  • SQS queue để lưu trữ và quản lý các bản tin tác vụ – Tên là TaskQueue
  • Một SQS queue hoạt động như một DLQ(Dead Letter Queue).

DLQ sẽ thu thập các bản tin mà các trình xử lý bị lỗi tại các bản tin đó. Ví dụ: Một bản tin sẽ được chuyển vào DLQ nếu Consumer hoặc Worker không hoàn thành nhiệm vụ trong vòng 90 giây trong 10 lần liên tiếp. Cơ chế này giúp cho hệ thống của bạn bỏ qua các bản tin bị lỗi mà không chặn việc xử lý các tác vụ khác trong hàng đợi.

Tiếp theo, tiến hành xây dựng Consumer.

Thiết lập và triển khai Consumer với Lambda

Đoạn code dưới đây chứ tất cả các tài nguyên cần thiết cho một Lambda Consumer:

  • Một IAM Rule có tên ConsumerLambdaRole bao gồm các rule cho phép Lambda Consumer trigger các Lambda Worker.
  • Lambda Function có tên ConsumerLambda và quy tắc SQS sẽ trigger function này khi có bản ghi mới được thêm vào hàng chờ.

Đoạn code trên để thiết lập các tài nguyên cần thiết cho ConsumerLambda function, phần còn thiếu là mã nguồn thực thi của ConsumerLambda function, hàm này sẽ thực hiện chức năng:

  • Nhận các bản ghi (tasks) từ SQS queue.
  • Gọi các worker để xử lý từng bản ghi (task).

Đoạn mã dưới đây được viết bằng Typescript, đoạn code thực hiện những nội dung ở trên:

Thiết lập Lambda Worker

Đoạn mã sau sử dụng cú pháp của CloudFormation, đoạn mã mô tả các tài nguyên cần thiết để thiết lập Lambda worker function.

  • IAM Rule cho phép hàm này có thể xóa các bản ghi của SQS
  • Một Lambda function có tên WorkerLambda.

Tất nhiên, bạn phải có code cho hàm WorkerLambda. Bạn có thể làm bất kỳ việc gì trong hàm này trong vòng 900 giây (15 phút). Bản ghi SQS cần phải được xóa khi đã được xử lý thành công.

Đoạn code dưới đây là một ví dụ cho hàm worker, không có công việc cụ thể nào được mô tả ở đây, nó chỉ cho bạn biết cách chúng ta triển khai:

Tổng kết

SQS giúp chúng ta triển khi ứng dụng mới mô hình microservice một cách dễ dàng, nó tách rời các khối công việc không đồng bộ của hệ thống.

Tài nguyên trong bài viết: https://gist.github.com/hoangsetup/51694cc7672308aa53a08ff475409c2a