Xây dựng API messaging có khả năng mở rộng với AWS End User Messaging và Amazon Simple Email Service

Tác giả: Bruno Giorgini và Tyler Holmes
Ngày phát hành: 24 MAR 2026
Chuyên mục: Advanced (300), Amazon Simple Email Service (SES), AWS End User Messaging, Messaging

Các ứng dụng hiện đại thường cần gửi thông báo qua nhiều kênh, bao gồm email và/hoặc SMS. Tuy nhiên, việc xây dựng một hệ thống nhắn tin đáng tin cậy có khả năng quản lý mẫu, xử lý lỗi một cách linh hoạt, mở rộng quy mô và duy trì bảo mật có thể là một thách thức. Theo hướng dẫn này, bạn sẽ học cách xây dựng một trình quản lý mẫu và API nhắn tin sử dụng API Gateway với xác thực JWT để truy cập an toàn, Amazon SQS để xếp hàng tin nhắn đáng tin cậy, AWS Lambda để xử lý phi máy chủ, AWS End User Messaging cho SMS và Amazon Simple Email Service (SES) cho email.

Tổng quan kiến trúc

Bạn triển khai một kiến trúc tách rời, phân tách việc tiếp nhận tin nhắn khỏi quá trình xử lý, mang lại khả năng phục hồi và mở rộng.


Hình 1: Kiến trúc Trình quản lý mẫu tin nhắn

Luồng kiến trúc

  1. Ứng dụng khách gửi các yêu cầu đã được xác thực bằng JWT token.
  2. API Gateway xác thực các yêu cầu bằng Lambda Authorizer.
  3. Lambda Authorizer truy xuất JWT secret từ AWS Secrets Manager và xác thực token.
  4. API Gateway gửi các tin nhắn đã được xác thực đến hàng đợi SQS.
  5. Lambda Processor thăm dò tin nhắn từ SQS theo lô.
  6. Lambda Processor truy xuất các mẫu tin nhắn từ DynamoDB (nếu cần).
  7. Lambda Processor gửi email qua Amazon SES và SMS qua AWS End User Messaging.
  8. Các tin nhắn lỗi (sau 3 lần thử lại) được chuyển đến Dead Letter Queue.
  9. CloudWatch Alarm kích hoạt khi tin nhắn đến DLQ.

Nếu một tin nhắn không được xử lý sau ba lần thử, nó sẽ được chuyển đến Dead Letter Queue (DLQ) nơi nó được lưu giữ trong 14 ngày và một cảnh báo CloudWatch sẽ thông báo cho bạn về lỗi đó.

Các tính năng chính

Với kiến trúc này, bạn nhận được một số khả năng quan trọng:

  • Xác thực JWT: Truy cập API an toàn bằng JSON Web Tokens được lưu trữ trong AWS Secrets Manager.
  • Tự động thử lại: Các tin nhắn lỗi được thử lại tối đa ba lần trước khi chuyển đến DLQ.
  • Lỗi lô một phần: Chỉ các tin nhắn lỗi được thử lại, không phải toàn bộ lô.
  • Quản lý mẫu: Lưu trữ các mẫu tin nhắn có thể tái sử dụng trong Amazon DynamoDB.
  • Hỗ trợ đa kênh: Gửi email qua Amazon SES và SMS qua AWS End User Messaging.
  • Hỗ trợ Configuration Set: Theo dõi các chỉ số phân phối và định tuyến sự kiện với các Configuration Set ở cấp độ tin nhắn hoặc cấp độ triển khai.
  • Giám sát: Các cảnh báo CloudWatch thông báo cho bạn khi tin nhắn bị lỗi.

Chi tiết triển khai

1. API Gateway với ủy quyền JWT

API Gateway sử dụng Lambda authorizer để xác thực JWT token trước khi cho phép các yêu cầu đi qua:

def lambda_handler(event, context):
token = event.get('authorizationToken', '').replace('Bearer ', '')
try:
# Retrieve secret from AWS Secrets Manager
jwt_secret = get_jwt_secret()
# Validate JWT token
payload = jwt.decode(
token,
jwt_secret,
algorithms=['HS256'],
issuer='messaging-api'
)
# Generate IAM policy to allow request
return generate_policy(payload.get('sub'), 'Allow', event['methodArn'])
except jwt.ExpiredSignatureError:
raise Exception('Unauthorized: Token expired')
except jwt.InvalidTokenError:
raise Exception('Unauthorized: Invalid token')

JWT secret được lưu trữ an toàn trong AWS Secrets Manager và được lưu vào bộ nhớ cache trong môi trường thực thi Lambda để tăng hiệu suất.

2. Cấu hình hàng đợi SQS

Mẫu SAM định nghĩa hai hàng đợi với các cài đặt phù hợp:

MessagesQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: MessagesQueue
VisibilityTimeout: 300 # 5 minutes
MessageRetentionPeriod: 345600 # 4 days
RedrivePolicy:
deadLetterTargetArn: !GetAtt MessagesDeadLetterQueue.Arn
maxReceiveCount: 3
MessagesDeadLetterQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: MessagesDeadLetterQueue
MessageRetentionPeriod: 1209600 # 14 days

Thời gian chờ hiển thị (visibility timeout) là 5 phút ngăn chặn việc xử lý trùng lặp trong khi vẫn cung cấp đủ thời gian cho hàm Lambda hoàn thành. Các tin nhắn bị lỗi ba lần sẽ tự động chuyển đến DLQ.

3. Bộ xử lý tin nhắn Lambda

Hàm Lambda xử lý tin nhắn từ SQS và gửi chúng qua kênh thích hợp:

def lambda_handler(event, context):
failed_messages = []
for record in event['Records']:
message_id = record['messageId']
try:
message = json.loads(record['body'])
# Process email if configured
if 'EmailMessage' in message:
send_emails(message)
# Process SMS if configured
if 'SMSMessage' in message:
send_sms_messages(message)
except Exception as e:
print(f"Error processing message {message_id}: {str(e)}")
failed_messages.append({"itemIdentifier": message_id})
# Return failed messages for automatic retry
return {"batchItemFailures": failed_messages}

Configuration Sets để theo dõi và phân tích:

Configuration Sets cho phép bạn theo dõi các chỉ số phân phối, giám sát chi phí và định tuyến các sự kiện đến các pipeline phân tích. Bạn có thể đặt các giá trị mặc định tại thời điểm triển khai và ghi đè chúng cho từng tin nhắn:

  • Mặc định cấp độ triển khai: Đặt tham số SMSConfigurationSet trong quá trình triển khai để áp dụng cho tất cả các tin nhắn.
  • Ghi đè từng tin nhắn: Bao gồm ConfigurationSetName trong payload SMSMessage để sử dụng theo dõi khác nhau cho các tin nhắn cụ thể.

Sự linh hoạt này cho phép bạn tách biệt phân tích theo loại tin nhắn, chiến dịch hoặc mức độ ưu tiên mà không yêu cầu triển khai lại.

4. Quản lý mẫu với DynamoDB

Các mẫu tin nhắn được lưu trữ trong DynamoDB để có thể tái sử dụng:

def get_email_template_from_dynamodb(template_name, substitutions):
response = templates_table.get_item(Key={'TemplateName': template_name})
if 'Item' not in response:
return build_default_email(), "Account Alert"
template_body = response['Item']['MessageBody']
subject = response['Item'].get('Subject', 'Notification')
# Replace {variable} placeholders with actual values
rendered_body = replace_variables(template_body, substitutions)
rendered_subject = replace_variables(subject, substitutions)
return rendered_body, rendered_subject

Bạn có thể cập nhật nội dung tin nhắn mà không cần triển khai lại mã.

Những cân nhắc về kích thước mẫu:

DynamoDB có giới hạn 400 KB cho mỗi mục, bao gồm tất cả tên và giá trị thuộc tính. Đối với các mẫu tin nhắn, điều này có nghĩa là:

  • Các mẫu email điển hình (5-20 KB) phù hợp thoải mái.
  • Các mẫu SMS (< 1 KB) không có hạn chế thực tế.

Nếu bạn cần lưu trữ các mẫu lớn hơn 400 KB, hãy cân nhắc lưu trữ chúng trong Amazon S3 và tham chiếu khóa đối tượng S3 trong DynamoDB. Cách tiếp cận kết hợp này cung cấp kích thước mẫu không giới hạn trong khi vẫn duy trì khả năng tra cứu nhanh chóng.

Điều kiện tiên quyết

Trước khi triển khai giải pháp này, hãy đảm bảo bạn có những điều sau:

  • AWS End User Messaging SMS được cấu hình với phone pool hoặc origination identity để gửi SMS.
  • Amazon SES được cấu hình với các email identity đã được xác minh (người gửi và người nhận cho chế độ sandbox).
  • Quyền IAM để tạo các hàm Lambda, API Gateway, hàng đợi SQS, bảng DynamoDB và Secrets Manager secrets.
  • Python 3.9 trở lên được cài đặt cục bộ.
  • AWS SAM CLI được cài đặt (phiên bản 1.0 trở lên).
  • AWS CLI được cài đặt và cấu hình với thông tin xác thực của bạn.
  • Một tài khoản AWS đang hoạt động với các quyền thích hợp.

Triển khai

Bạn sử dụng AWS SAM cho cơ sở hạ tầng dưới dạng mã. Triển khai bằng các lệnh sau:

sam build
sam deploy --guided

Trong quá trình triển khai, bạn sẽ đặt một JWT secret được lưu trữ trong AWS Secrets Manager. Sử dụng một secret mạnh, ngẫu nhiên cho môi trường sản xuất:

python -c "import secrets; print(secrets.token_urlsafe(32))"

Ví dụ sử dụng

Sau khi triển khai, hãy gửi tin nhắn bằng cách thực hiện các yêu cầu API đã được xác thực:

curl -X POST "https://your-api-endpoint/dev/" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"TraceId": "12345",
"EmailMessage": {
"FromAddress": "alerts@example.com",
"Subject": "Low Balance Alert",
"ConfigurationSetName": "email-analytics",
"Substitutions": {
"productName": "CHEQUING",
"membershipNumber": "****5493",
"accountBalance": "100.00"
}
},
"SMSMessage": {
"MessageType": "TRANSACTIONAL",
"OriginationNumber": "your-pool-id",
"TemplateName": "alert-template",
"ConfigurationSetName": "sms-analytics"
},
"Addresses": {
"user@example.com": {
"ChannelType": "EMAIL"
},
"+16048621234": {
"ChannelType": "SMS",
"Substitutions": {
"productName": "CHEQUING",
"membershipNumber": "****7303",
"accountBalance": "100.00"
}
}
}
}'

Sử dụng Configuration Sets:

Ví dụ trên cho thấy các tham số ConfigurationSetName tùy chọn cho cả email và SMS. Chúng cho phép:

  • Theo dõi phân phối: Giám sát tỷ lệ phân phối, lỗi và chỉ số bounce.
  • Giám sát chi phí: Theo dõi chi tiêu cho mỗi chiến dịch hoặc loại tin nhắn.
  • Định tuyến sự kiện: Gửi các sự kiện phân phối đến CloudWatch, Kinesis hoặc SNS để phân tích.
  • Các chỉ số phân đoạn: Tách biệt phân tích theo trường hợp sử dụng, mức độ ưu tiên hoặc phân khúc khách hàng.

Nếu bạn không chỉ định ConfigurationSetName trong yêu cầu, hệ thống sẽ sử dụng giá trị mặc định cấp độ triển khai (nếu được cấu hình).

Giám sát và vận hành

CloudWatch alarms

Giải pháp bao gồm một cảnh báo CloudWatch kích hoạt khi tin nhắn đến DLQ:

DLQAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub ${AWS::StackName}-DLQ-Messages
MetricName: ApproximateNumberOfMessagesVisible
Namespace: AWS/SQS
Statistic: Sum
Period: 300
EvaluationPeriods: 1
Threshold: 1
ComparisonOperator: GreaterThanOrEqualToThreshold

Xử lý tin nhắn lỗi

Khi tin nhắn bị lỗi, bạn có thể kiểm tra chúng trong DLQ và chuyển chúng trở lại hàng đợi chính sau khi khắc phục sự cố:

# Check DLQ depth
aws sqs get-queue-attributes \
--queue-url YOUR_DLQ_URL \
--attribute-names ApproximateNumberOfMessages
# Redrive messages from DLQ to main queue
aws sqs start-message-move-task \
--source-arn YOUR_DLQ_ARN \
--destination-arn YOUR_MAIN_QUEUE_ARN

Xem nhật ký

Lambda tự động ghi nhật ký vào CloudWatch Logs:

aws logs tail /aws/lambda/MessageProcessor --follow

Chi phí ước tính

Đối với 1 triệu tin nhắn mỗi tháng, chi phí ước tính là:

Dịch vụSử dụngChi phí
API Gateway1M yêu cầu$3.50
Amazon SQS1M tin nhắn$0.40
AWS Lambda1M lời gọi (128MB, trung bình 1s)$2.50
Amazon SES1M email$100.00
AWS End User Messaging SMS1M SMS$ Thay đổi tùy theo điểm đến

Lưu ý: Kiến trúc phi máy chủ có nghĩa là bạn chỉ trả tiền cho những gì bạn sử dụng, không có phí tối thiểu hoặc chi phí trả trước.

Các phương pháp bảo mật tốt nhất

Giải pháp này tuân theo một số phương pháp bảo mật tốt nhất:

  1. Xác thực JWT: Tất cả các yêu cầu API đều yêu cầu JWT token hợp lệ.
  2. Secrets Manager: JWT secrets được lưu trữ mã hóa trong AWS Secrets Manager.
  3. IAM Least Privilege: Mỗi hàm Lambda chỉ có các quyền mà nó cần.
  4. Chỉ HTTPS: API Gateway thực thi HTTPS cho tất cả các yêu cầu.
  5. Token Caching: Các quyết định ủy quyền được lưu vào bộ nhớ cache trong 5 phút để giảm độ trễ.

Dọn dẹp tài nguyên

Để tránh phát sinh chi phí liên tục, hãy xóa các tài nguyên được tạo bởi giải pháp này khi bạn không còn cần chúng nữa:

  1. Nếu bạn đã cấu hình AWS End User Messaging phone pools hoặc origination identities cho giải pháp này, hãy xóa chúng khỏi bảng điều khiển End User Messaging.
  2. Nếu bạn đã tạo Amazon SES email identities cụ thể cho giải pháp này, hãy xóa chúng khỏi bảng điều khiển SES.
  3. Xác minh rằng tất cả các tài nguyên (các hàm Lambda, API Gateway, hàng đợi SQS, bảng DynamoDB, Secrets Manager secret) đã được xóa trong AWS Management Console.
  4. Xóa stack CloudFormation bằng cách chạy: sam delete --stack-name <your-stack-name>

Kết luận

Với kiến trúc này, bạn có thể xây dựng một API nhắn tin sẵn sàng cho sản xuất bằng cách sử dụng các dịch vụ phi máy chủ của AWS. Thiết kế tách rời mang lại khả năng phục hồi thông qua các lần thử lại tự động và hàng đợi thư chết, trong khi cách tiếp cận phi máy chủ loại bỏ việc quản lý cơ sở hạ tầng và tự động mở rộng quy mô.

Giải pháp hoàn chỉnh có thể triển khai thông qua AWS SAM và bao gồm:

  • Xác thực JWT với AWS Secrets Manager.
  • Nhắn tin đa kênh (email và SMS).
  • Quản lý mẫu với DynamoDB.
  • Hỗ trợ Configuration Set để theo dõi và phân tích.
  • Giám sát và cảnh báo toàn diện.
  • Xử lý thử lại và lỗi tự động.

Bạn có thể mở rộng kiến trúc này bằng cách thêm nhiều kênh hơn (thông báo đẩy, webhook), triển khai lập lịch tin nhắn hoặc tích hợp với Amazon EventBridge cho các quy trình làm việc dựa trên sự kiện.

Tài nguyên bổ sung

Mã nguồn hoàn chỉnh cho giải pháp này có sẵn trong kho lưu trữ GitHub đi kèm, bao gồm các mẫu SAM, hàm Lambda và tập lệnh triển khai.


Về tác giả


Bruno Giorgini
Bruno Giorgini là Kiến trúc sư Giải pháp cấp cao chuyên về Dịch vụ Phát triển Truyền thông của AWS. Khi không tạo ra các giải pháp sáng tạo cho khách hàng, Bruno thích dành thời gian chất lượng bên gia đình, khám phá những con đường mòn đi bộ đường dài tuyệt đẹp. Niềm đam mê công nghệ và tiềm năng của nó trong việc thúc đẩy chuyển đổi kinh doanh giúp anh ấy luôn có động lực để mang lại các giải pháp có tác động cho các tổ chức trên toàn thế giới.


Tyler Holmes
Tyler là Kiến trúc sư Giải pháp Chuyên gia cấp cao. Anh ấy có nhiều kinh nghiệm trong lĩnh vực truyền thông với vai trò tư vấn, SA, người thực hành và lãnh đạo ở mọi cấp độ từ Startup đến Fortune 500. Anh ấy đã dành hơn 14 năm trong các hoạt động bán hàng, tiếp thị và dịch vụ, làm việc cho các agency, công ty tư vấn và thương hiệu, xây dựng đội ngũ và tăng doanh thu.

Leave a comment