Tổng quan về Amazon SQS và sử dụng nó trong Ruby

Amazon SQS

Amazon SQS

Amazon Simple Queue Service (SQS) là một dịch vụ hàng đợi (queue) lưu trữ thông điệp (message) nhanh chóng, đáng tin cậy, có khả năng mở rộng và quản lý một cách đầy đủ. Amazon SQS giúp bạn có thể di chuyển dữ liệu giữa các thành phần phân tán của ứng dụng của bạn để thực hiện các nhiệm vụ khác nhau. Bạn có thể sử dụng SQS để truyền tải bất kỳ khối lượng dữ liệu, ở bất kỳ mức độ thông lượng nào mà không sợ bị mất đi các thông điệp hoặc yêu cầu của mỗi thành phần là luôn luôn có sẵn.

Với SQS, bạn có thể giảm tải gánh nặng cho hệ thống và có thể dễ dàng mở rộng thông điệp lưu trữ, trong khi chỉ phải trả chi phí thấp cho những gì bạn sử dụng.

Một số đặc tính cung cấp bởi SQS

  • Tính tin cậy

Amazon SQS hoạt động bên trong một trung tâm dữ liệu có tính sẵn sàng cao của Amazon, do đó các hàng đợi sẽ có mặt bất cứ khi nào các ứng dụng cần đến chúng. Để ngăn chặn các thông điệp không bị mất mát hay không có sẵn, tất cả các thông điệp sẽ được lưu trữ dự phòng trên nhiều máy chủ và trung tâm dữ liệu.

  • Tính đơn giản

Mô hình lập trình cho việc truy cập, sử dụng SQS rất đơn giản và có thể được sử dụng cho nhiều ngôn ngữ lập trình khác nhau.

  • Khả năng mở rộng

Amazon SQS được thiết kế cho phép bạn có khả năng tạo các ứng dụng dựa trên hàng đợi mà có thể đọc và ghi các thông điệp không giới hạn tại bất kỳ thời điểm nào.

  • Bảo mật

Cơ chế xác thực được cung cấp để đảm bảo rằng các thông điệp được lưu trữ trong các hàng đợi của Amazon SQS được đảm bảo chống truy cập trái phép.

  • Không tốn kém

Không có trả trước hay là chi phí cố định. Các chi phí gửi thông điệp thông qua Amazon SQS là thấp trên mỗi yêu cầu xử lý và chuyển dữ liệu.

Sau đây là bảng giá khi sử dụng các dịch vụ của Amazon SQS cho đến thời điểm hiện tại:

Amazon SQS Pricing

Tổng quan về kiến trúc

Hệ thống tổng thế gồm có 3 phần chính:

  • Các thành phần của hệ thống phân tán của bạn
  • Các hàng đợi
  • Các thông điệp trong các hàng đợi

Trong hình bên dưới, hệ thống gồm một số thành phần phân tán gửi thông điệp tới hàng đợi và nhận thông điệp từ hàng đợi. Hình dưới cho thấy một hàng đợi có nhiều thông điệp và chúng được lưu trữ dự phòng trên nhiều máy chủ của Amazon SQS.

ArchOverview.png

Hàng đợi (queue)

Hàng đợi là một kho lưu trữ tạm thời các thông điệp chờ xử lý. Mỗi thông điệp phải chỉ rõ một hàng đợi sẽ chứa nó. Các thông điệp được gửi tới hàng đợi sẽ ở đó cho đến khi bạn thực sự xóa chúng. Trật tự của hàng đợi là vào trước, ra trước, nhưng trật từ này không được đảm bảo. Mỗi hàng đợi đều có một thời gian chờ hiển thị (visibility timeout) mặc định là 30s. Bạn có thể thay đổi giá trị này cho toàn bộ hàng đợi, hoặc nó có thể được đặt riêng lẻ cho từng thông điệp. Thời gian chờ hiển thị tối đa cho một hàng đợi hay thông điệp là 43200s (12 hours). Amazon SQS duy trì quyền xóa hàng đợi một cách tự động nếu không có hoạt động thực sự nào trên hàng đợi trong vòng 30 ngày liên tục.

Mỗi khi tạo một hàng đợi, bạn phải cung cấp QueueName duy nhất cho nó. Amazon SQS sẽ gán cho mỗi hàng đợi bạn tạo ra một định danh gọi là QueueUrl, nó bao gồm QueueName và một số thành phần khác. Mỗi khi bạn muốn thực hiện một hành động trên một hàng đợi, bạn phải cung cấp cho nó một QueueUrl.

Sau đây là QueueUrl cho QueueName = "queue1", thuộc về tài khoản AWS là "123456789012":

http://sqs.us-east-1.amazonaws.com/123456789012/queue1

Thông điệp (message)

Các thông điệp có thể chứa dữ liệu văn bản với dung lượng lên tới 256 KB. Thành phần của một thông điệp:

  • MessageId: Một định danh ID duy nhất tham chiếu tới một thông điệp. Độ dài tối đa của một MessageId là 100 kí tự.
  • ReceiptHandle: Một trình xử lý duy nhất được trả về khi một thông điệp được nhận từ hàng đợi. Giá trị này là khác nhau với mỗi lần lấy một thông điệp từ hàng đợi. Nó được yêu cầu khi bạn xóa thông điệp hoặc thay đổi giá trị visibility timeout. Giá trị tối đa của một ReceiptHandle là 1024 kí tự.
  • MD5OfBody: Mã MD5 của chuỗi thông điệp không bị mã hóa.
  • Body: Dữ liệu thực sự của thông điệp.

Khi một thành phần trong hệ thống của bạn nhận và xử lý một thông điệp từ hàng đợi, thông điệp đó vẫn còn ở trong hàng đợi mà không bị xóa đi. Bởi vì hệ thống của bạn là phân tán, không có đảm bảo rằng các thành phần đã thực sự nhận được thông điệp (có thể kết nối bị phá vỡ hoặc thành phần có thể bị lỗi trước khi nhận thông điệp). Do đó, Amazon SQS không xóa thông điệp đó, và thay vào đó, thành phần nhận thông điệp phải tiến hành xóa nó từ hàng đợi sau khi đã xử lý nó xong.

Ngay sau khi một thành phần nhận được thông điệp, nó vẫn còn ở trong hàng đợi. Tuy nhiên, bạn không muốn một thành phần khác trong hệ thống nhận và xử lý nó một lần nữa. Do đó, Amazon SQS đã khóa chúng với một thời gian chờ hiển thị (visibility timeout), đó là khoảng thời gian mà Amazon SQS ngăn chặn các thành phần khác không nhận và xử lý thông điệp đó một lần nữa. Hình dưới đây sẽ minh họa điều đó: Visibility_Timeout.png

Vòng đời của một thông điệp, đặt tên là thông điệp A, từ lúc được tạo ra đến lúc bị xóa được thể hiện ở hình dưới đây: MessageLifecycle.png

  1. Thành phần 1 gửi thông điệp A tới một hàng đợi, thông điệp đó được lưu dự phòng trên nhiều máy chủ SQS.
  2. Khi thành phần 2 đã sẵn sàng để xử lý một thông điệp, nó lấy các thông điệp từ hàng đợi và thông điệp A được trả về. Trong khi thông điệp A được xử lý, nó vẫn còn lại ở trong hàng đợi và không được trả về cho các yêu cầu nhận tiếp theo trong thời gian chờ hiển thị (visibility timeout).
  3. Sau khi thành phần 2 xử lý xong thông điệp A, nó sẽ xóa thông điệp A từ hàng đợi để tránh thông điệp đó được nhận và xử lý một lần nữa.

Cân nhắc thiết kế

SQS hơi khác một chút so với các dịch vụ hàng đợi thông dụng. Có ba thứ bạn cần cân nhắc trước khi thiết kế ứng dụng dựa trên SQS của bạn:

  • SQS không đảm bảo trật tự của các thông điệp trong một hàng đợi. Các thông điệp được sắp xếp trong một hàng đợi, chúng không thực sự được lưu trữ theo trật tự mà chúng được thêm vào hàng đợt. SQS sẽ cố để duy trì trật tự trong các thông điệp, nhưng nó không đảm bảo rằng bạn sẽ nhận được các thông điệp theo trật tự chính xác như khi bạn gửi. Nếu trật tự của thông điệp là quan trọng với ứng dụng của bạn, bạn cần phải thêm dữ liệu tuần tự vào mỗi thông điệp.

  • SQS không đảm bảo sự xóa của một thông điệp trong hàng đợi. Bạn phải thiết kế ứng dụng của bạn sao cho nó không bị ảnh hưởng nếu cùng một thông điệp được xử lý nhiều hơn một lần. Mỗi thông điệp của bạn được lưu trữ trên nhiều máy chủ khác nhau bởi SQS, để cung cấp tính dự phòng và tính sẵn sàng cao. Nếu một trong các máy chủ này không hoạt động trong khi một thông điệp đang bị xóa, bạn có thể nhận được một bản sao của thông điệp trong khi nhận các thông điệp.

  • SQS không đảm bảo tất cả các thông điệp trong hàng đợi sẽ được trả lại khi được yêu cầu. SQS sử dụng việc lấy mẫu thông điệp dựa trên phân bố ngẫu nhiên có trọng số, và nó trả lại thông điệp chỉ từ những tập con được lấy mẫu của các máy chủ khi bạn yêu cầu các thông điệp. Thậm chí, một yêu cầu cụ thể có thể sẽ không trả lại tất cả các thông điệp trong hàng đợi, nếu bạn tiếp tục nhận thông điệp từ hàng đợi nó sẽ kết thúc việc lấy mẫu tất cả các máy chủ và bạn sẽ nhận được tất cả các thông điệp của bạn.

Bắt đầu với Amazon SQS API trong Ruby

Để bắt đầu khám phá SQS, đầu tiên bạn phải đăng ký một tài khoản trên Amazon Web Services tại http://aws.amazon.com.

Để có thể sử dụng các API của Amazon SQS, bạn cần có một access key, trong đó chứa một access key IDsecret access key. Nếu không có một access key, bạn cũng có thể sử dụng AWS Management Console để tạo ra các yêu cầu tới Amazon SQS. Tôi khuyên bạn nên sử dụng IAM access key thay vì acccess key của tài khoản gốc Amazon. IAM giúp cho cho bạn điều khiển truy cập tới các dịch vụ và tài nguyên của Amazon một cách an toàn hơn.

Hãy làm theo các bước sau đây để có thể có một access key:

  1. Truy cập vào IAM console
  2. Click vào tab Users.
  3. Chọn IAM user name của bạn
  4. Click vào User Actions, sau đó cho chọn Manage Access Keys.
  5. Click vào Create Access Key. Access key của bạn sẽ giống như thế này:
  • Access key ID example: AKIAIOSFODNN7EXAMPLE
  • Secret access key example: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
  1. Cuối cùng chọn Download Credentials để lưu trữ access key của mình để sử dụng.

Cấu hình

Để bắt đầu sử dụng các API của Amazon SQS với Ruby, trước hết bạn thêm aws-sdk gem vào trong Gemfile để cài đặt AWS SDK cho Ruby. Ở đây, chúng ta sẽ sử dụng phiên bản mới nhất của AWS SDK là version 2.

# Gemfile
gem 'aws-sdk', '~> 2'

Sau đó, chúng ta cần tiến hành cấu hình access keyregion thông qua Aws.config:

AWS.config.update({
  access_key_id: 'ACCESS_KEY_ID',
  secret_access_key: 'SECRET_ACCESS_KEY',
  region: 'REGION',
})

Các bước cấu hình đã xong, giờ thì chúng ta cùng bắt đầu sử dụng các API của Amazon SQS:

Trước hết, chúng ta tạo một client để tạo các API requests tới Amazon SQS:

sqs_client = Aws::SQS::Client.new

Một số API chính của Amazon SQS

** Tạo mới một hàng đợi có tên là simple_queue_1 **:

resp = sqs_client.create_queue(queue_name: "simple_queue_1")

** Liệt kê các hàng đợi của bạn **

resp = client.list_queues(queue_name_prefix: "String")

Trong đó queue_name_prefix là một string dùng để lọc lấy kết quả trả về, chỉ có những hàng đợi có tên bắt đầu với chuỗi đó được trả về.

** Lấy queue URL **

Mỗi request gửi lên để truy cập vào một hàng đợi nào đó cần được cung cấp một queue URL. Do đó, thao tác sau giúp lấy URL của một hàng đợi đã tồn tại.

resp = client.get_queue_url(queue_name: "String")

** Xóa một hàng đợi **

resp = client.delete_queue(queue_url: "String")

Thao tác này giúp xóa một hàng đợi từ SQS bằng queue URL.

** Gửi một thông điệp lên một hàng đợi **

resp = client.send_message({
  queue_url: "String",
  message_body: "String",
})

Trong đó, message_body là nội dung của thông điệp bạn cần gửi. Dung lượng tối đa của một thông điệp là 256 KB.

** Gửi nhiều thông điệp lên hàng đợi **

resp = client.send_message_batch({
  queue_url: "String",
  entries: [
    {
      id: "String",
      message_body: "String",
    },
  ],
})

** Nhận một hoặc nhiều thông điệp từ hàng đợi **

resp = client.receive_message({
  queue_url: "String",
  max_number_of_messages: 1,
  visibility_timeout: 1,
})

Thao tác này cho phép nhận tối đa là 10 thông điệp từ một hàng đợi nào đó.

** Thay đổi giá trị thời gian chờ hiển thị **

resp = client.change_message_visibility({
  queue_url: "String",
  receipt_handle: "String",
  visibility_timeout: 1,
})

** Xóa một thông điệp **

resp = client.delete_message({
  queue_url: "String",
  receipt_handle: "String",
})

Còn một số API nữa mà tôi chưa nhắc đến ở đây, các bạn có thể tìm hiểu thêm tại đây: AWS SQS API </br>

Hi vọng bài viết này sẽ giúp ích cho bạn đọc áp dụng một cách có hiệu quả nhất Amazon SQS vào ứng dụng của mình. (dance3)

Nguồn tham khảo

  1. http://docs.aws.amazon.com/sdkforruby/api/Aws/SQS/Client.html
  2. http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/Welcome.html