关于 sns
面向使用 Amazon SNS 进行发布/订阅消息传递的开发者的参考技能,涵盖主题、订阅、消息筛选、CLI 与 boto3 示例及投递故障排查。
主要功能
- 01Standard 与 FIFO 主题
- 02多种订阅协议
- 03基于属性的消息筛选
- 04AWS CLI 和 boto3 示例
- 05向多个 SQS 队列扇出
- 06投递故障排查
适用场景
- 01向主题订阅者发布通知
- 02通过订阅筛选器路由消息
- 03将消息扇出到 SQS 队列
- 04调查订阅端未收到消息的原因
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ itsmostafa/ aws-agent-skills --skill sns安装后在 Claude Code 中输入/sns确认已加载。
附带文件notification-patterns.md
详细介绍
AWS SNS
Amazon Simple Notification Service(SNS)是一项完全托管的发布/订阅消息服务,用于应用程序到应用程序(A2A)和应用程序到个人(A2P)的通信。
目录
核心概念
主题
用于发布消息的命名通道。发布者向主题发送消息,订阅者从主题接收消息。
主题类型
| 类型 | 描述 | 用例 |
|---|---|---|
| Standard | 尽力保证顺序,至少传递一次 | 大多数用例 |
| FIFO | 严格保证顺序,恰好传递一次 | 对顺序敏感的场景 |
订阅协议
| 协议 | 描述 |
|---|---|
| Lambda | 调用 Lambda 函数 |
| SQS | 发送到 SQS 队列 |
| HTTP/HTTPS | 向端点发送 POST 请求 |
| 发送电子邮件 | |
| SMS | 发送短信 |
| Application | 移动推送通知 |
消息筛选
根据消息属性将消息路由到特定订阅者。
常见模式
创建主题并订阅
AWS CLI:
# Create standard topic
aws sns create-topic --name my-topic
# Create FIFO topic
aws sns create-topic \
--name my-topic.fifo \
--attributes FifoTopic=true
# Subscribe Lambda
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:123456789012:my-topic \
--protocol lambda \
--notification-endpoint arn:aws:lambda:us-east-1:123456789012:function:my-function
# Subscribe SQS
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:123456789012:my-topic \
--protocol sqs \
--notification-endpoint arn:aws:sqs:us-east-1:123456789012:my-queue
# Subscribe email
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:123456789012:my-topic \
--protocol email \
--notification-endpoint [email protected]
boto3:
import boto3
sns = boto3.client('sns')
# Create topic
response = sns.create_topic(Name='my-topic')
topic_arn = response['TopicArn']
# Subscribe Lambda
sns.subscribe(
TopicArn=topic_arn,
Protocol='lambda',
Endpoint='arn:aws:lambda:us-east-1:123456789012:function:my-function'
)
# Subscribe SQS with filter
sns.subscribe(
TopicArn=topic_arn,
Protocol='sqs',
Endpoint='arn:aws:sqs:us-east-1:123456789012:order-queue',
Attributes={
'FilterPolicy': '{"event_type": ["order_created", "order_updated"]}'
}
)
发布消息
import boto3
import json
sns = boto3.client('sns')
topic_arn = 'arn:aws:sns:us-east-1:123456789012:my-topic'
# Simple publish
sns.publish(
TopicArn=topic_arn,
Message='Hello, World!',
Subject='Notification'
)
# Publish with attributes (for filtering)
sns.publish(
TopicArn=topic_arn,
Message=json.dumps({'order_id': '12345', 'status': 'created'}),
MessageAttributes={
'event_type': {
'DataType': 'String',
'StringValue': 'order_created'
},
'priority': {
'DataType': 'Number',
'StringValue': '1'
}
}
)
# Publish to FIFO topic
sns.publish(
TopicArn='arn:aws:sns:us-east-1:123456789012:my-topic.fifo',
Message=json.dumps({'order_id': '12345'}),
MessageGroupId='order-12345',
MessageDeduplicationId='unique-id'
)
消息筛选
# Add filter policy to subscription
aws sns set-subscription-attributes \
--subscription-arn arn:aws:sns:us-east-1:123456789012:my-topic:abc123 \
--attribute-name FilterPolicy \
--attribute-value '{
"event_type": ["order_created"],
"priority": [{"numeric": [">=", 1]}]
}'
筛选策略示例:
// Exact match
{"event_type": ["order_created", "order_updated"]}
// Prefix match
{"customer_id": [{"prefix": "PREMIUM-"}]}
// Numeric comparison
{"price": [{"numeric": [">=", 100, "<=", 500]}]}
// Exists check
{"customer_id": [{"exists": true}]}
// Anything but
{"event_type": [{"anything-but": ["deleted"]}]}
// Combined
{
"event_type": ["order_created"],
"region": ["us-east", "us-west"],
"priority": [{"numeric": [">=", 1]}]
}
扇出模式(SNS 到多个 SQS)
import boto3
import json
sns = boto3.client('sns')
sqs = boto3.client('sqs')
# Create topic
topic = sns.create_topic(Name='orders-topic')
topic_arn = topic['TopicArn']
# Create queues for different processors
queues = {
'analytics': sqs.create_queue(QueueName='order-analytics')['QueueUrl'],
'fulfillment': sqs.create_queue(QueueName='order-fulfillment')['QueueUrl'],
'notification': sqs.create_queue(QueueName='order-notification')['QueueUrl']
}
# Subscribe each queue
for name, queue_url in queues.items():
queue_arn = sqs.get_queue_attributes(
QueueUrl=queue_url,
AttributeNames=['QueueArn']
)['Attributes']['QueueArn']
sns.subscribe(
TopicArn=topic_arn,
Protocol='sqs',
Endpoint=queue_arn
)
# One publish reaches all queues
sns.publish(
TopicArn=topic_arn,
Message=json.dumps({'order_id': '12345', 'total': 99.99})
)
SNS 的 Lambda 权限
aws lambda add-permission \
--function-name my-function \
--statement-id sns-trigger \
--action lambda:InvokeFunction \
--principal sns.amazonaws.com \
--source-arn arn:aws:sns:us-east-1:123456789012:my-topic
CLI 参考
主题管理
| 命令 | 描述 |
|---|---|
aws sns create-topic | 创建主题 |
aws sns delete-topic | 删除主题 |
aws sns list-topics | 列出主题 |
aws sns get-topic-attributes | 获取主题设置 |
aws sns set-topic-attributes | 更新主题设置 |
订阅
| 命令 | 描述 |
|---|---|
aws sns subscribe | 创建订阅 |
aws sns unsubscribe | 移除订阅 |
aws sns list-subscriptions | 列出所有订阅 |
aws sns list-subscriptions-by-topic | 列出主题订阅 |
aws sns confirm-subscription | 确认待处理的订阅 |
发布
| 命令 | 描述 |
|---|---|
aws sns publish | 发布消息 |
最佳实践
可靠性
- 使用 SQS 确保持久性 — SNS 基于推送,SQS 队列会对消息进行排队
- 为 HTTP/HTTPS 端点实现重试
- 为投递失败的消息配置 DLQ
- 对有顺序要求的场景使用 FIFO 主题
安全性
- 使用主题策略控制访问
- 启用 SSE 加密
- 使用 VPC 端点进行私有访问
# Enable SSE
aws sns set-topic-attributes \
--topic-arn arn:aws:sns:us-east-1:123456789012:my-topic \
--attribute-name KmsMasterKeyId \
--attribute-value alias/my-key
成本优化
- 使用消息筛选减少不必要的投递
- 尽可能批量执行操作
- 监控并清理未使用的主题/订阅
消息设计
- 保持消息简短(上限为 256 KB)
- 使用消息属性进行路由
- 包含关联 ID以便追踪
故障排查
订阅未收到消息
检查:
- 订阅已确认(而非待处理状态)
- 筛选策略与消息属性匹配
- 目标权限(Lambda、SQS)
# Check subscription status
aws sns list-subscriptions-by-topic \
--topic-arn arn:aws:sns:us-east-1:123456789012:my-topic
# Check subscription attributes
aws sns get-subscription-attributes \
--subscription-arn arn:aws:sns:us-east-1:123456789012:my-topic:abc123
HTTP 端点无法正常工作
调试:
# Check delivery status logging
aws sns set-topic-attributes \
--topic-arn arn:aws:sns:us-east-1:123456789012:my-topic \
--attribute-name DeliveryPolicy \
--attribute-value '{
"http": {
"defaultHealthyRetryPolicy": {
"minDelayTarget": 20,
"maxDelayTarget": 20,
"numRetries": 3,
"numMaxDelayRetries": 0,
"numNoDelayRetries": 0,
"numMinDelayRetries": 0,
"backoffFunction": "linear"
}
}
}'
消息与筛选条件不匹配
验证:
- 已设置消息属性(而非消息正文中的属性)
- 属性类型匹配(String 与 Number)
- 筛选策略语法正确
# Correct: attributes must be message attributes
sns.publish(
TopicArn=topic_arn,
Message='body content',
MessageAttributes={
'event_type': {
'DataType': 'String',
'StringValue': 'order_created' # This is filtered
}
}
)
# Wrong: this won't be filtered
sns.publish(
TopicArn=topic_arn,
Message=json.dumps({'event_type': 'order_created'}) # Not filtered
)
SQS 未从 SNS 接收消息
检查 SQS 队列策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"Service": "sns.amazonaws.com"},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:123456789012:my-queue",
"Condition": {
"ArnEquals": {
"aws:SourceArn": "arn:aws:sns:us-east-1:123456789012:my-topic"
}
}
}
]
}
参考资料
评论
支持 Markdown