如何在 SNS 订阅中添加 SQS 消息属性?

28

AWS SNS和SQS的文档中有关于消息属性的章节。但是没有解释如何在将队列订阅到SNS主题时设置SQS的消息属性。

是否有一种方法可以配置AWS SNS以向通过订阅发送的SQS消息添加特定的消息属性?


当Amazon SQS队列订阅了Amazon SNS主题时,SQS消息将包含发送到(并从)SNS转发的消息。您想要哪些特定属性? - John Rotenstein
“SQS消息属性”是一个独立于消息体之外的东西。 - Evgeny
这是正确的。然而,当SNS向SQS发送消息时,它会填充SQS消息正文。您希望从SNS中填充哪些属性作为SQS消息属性? - John Rotenstein
6
我希望在从此SNS主题生成的SQS消息上有特定预定义的属性。例如,一个主题上的消息会添加一个属性 path: foo,而发送到同一SQS队列的另一个SNS主题会添加一个属性 path: bar。根据 http://docs.aws.amazon.com/sns/latest/dg/SNSMessageAttributes.html,似乎有一个参考文档,但没有其他记录。 *重要提示*:要在Amazon SQS端点使用消息属性,必须将订阅属性“原始消息传递”设置为True。 - Evgeny
4个回答

50

根据 AWS 文档:

要在 Amazon SQS 端点中使用消息属性,您必须将订阅属性“原始消息传递”设置为 True。有关原始消息传递的详细信息,请参阅附录:大容量负载和原始消息传递。 https://docs.aws.amazon.com/sns/latest/dg/SNSMessageAttributes.html https://docs.aws.amazon.com/sns/latest/dg/large-payload-raw-message.html

下面是来自实际项目的示例 ,希望能帮助澄清问题。

发布到 SNS 主题的消息如下:

aws sns publish --topic-arn arn:aws:sns:us-west-2:xxx:pollution-event --message '{"operatorId":3375001,"eventTypeId":1,"eventLevelId":1,"validFrom":"2018-03-10T09:00:00Z","validTo":"2018-03-11T09:00:00Z"}'  --message-attributes '{"Type" : { "DataType":"String", "StringValue":"Orchestration.Services.Model.Pollution.PollutionMessage"}}'

启用原始传递为 false(默认)。从 SQS 接收的消息仅包含内容,没有属性。

{
  "Type": "Notification",
  "MessageId": "78d5bc6f-142c-5060-a75c-ef29b774ec66",
  "TopicArn": "arn:aws:sns:eu-west-2:xxx:pollution-event",
  "Message": "{\"validFrom\": \"2018-03-10T09:00:00Z\",\"validTo\": \"2018-03-11T09:00:00Z\",\"eventLevelId\": 1,\"eventTypeId\": 1,\"operatorId\": 3375001}",
  "Timestamp": "2018-04-17T11:33:44.770Z",
  "SignatureVersion": "1",
  "Signature": "xxx==",
  "SigningCertURL": "https://sns.eu-west-2.amazonaws.com/SimpleNotificationService-xxx.pem",
  "UnsubscribeURL": "https://sns.eu-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-2:xxx",
  "MessageAttributes": {
    "Type": {
      "Type": "String",
      "Value": "Orchestration.Services.Model.Pollution.PollutionMessage"
    },
    "AWS.SNS.MOBILE.MPNS.Type": {
      "Type": "String",
      "Value": "token"
    },
    "AWS.SNS.MOBILE.MPNS.NotificationClass": {
      "Type": "String",
      "Value": "realtime"
    },
    "AWS.SNS.MOBILE.WNS.Type": {
      "Type": "String",
      "Value": "wns/badge"
    }
  }
}

消息本身包含没有消息属性

启用原始传递为true。 消息包含消息属性和正确的内容 消息具有属性 该属性包含预期值


2
是的,我们遇到了完全相同的问题:我们发布了带有属性的消息,但是 SNS 转发时没有任何属性。SQS 包含一个包含属性的 JSON 内容的消息。启用原始消息传递解决了这个问题,即 SNS 按原样发送消息,属性保持不变。 - Borys Generalov
4
这应该是被采纳的答案。一旦您将原始设置从默认值更改,消息属性将正确显示在 SQS 中。 - Michael Oryl
1
非常奇怪。尽管这些属性在AWS控制台上显示,但它们通过SDK无法接收到。为什么会发生这种情况? - k.liakos
4
你需要传递--message-attribute-names参数才能接收消息属性。 - k.liakos
1
这是正确的答案。启用“原始消息传递”将会将消息属性从SNS传递到SQS,作为实际的消息属性而不是消息体的一部分。 - IMB
显示剩余5条评论

25

注意:查看其他答案以获得更好的响应,使用原始消息传递


在发送 Amazon SNS 消息属性到 Amazon SQS 的 使用 Amazon SNS 消息属性 文档中,似乎属性是作为消息的 主体 发送而不是作为结果 Amazon SQS 消息的属性附加发送。
例如,我执行了以下操作:
  • 创建了一个 Amazon SNS 主题
  • 创建了一个 Amazon SQS 队列并将其订阅到 SNS 主题
  • 发布了一条消息到 SNS
我通过 AWS 命令行界面 (CLI) 进行发布:
aws sns publish --topic-arn arn:aws:sns:ap-southeast-2:123456789012:foo --message msg --subject subj --message-attributes '{"somename" : { "DataType":"String", "StringValue":"somevalue"}}'

我从aws cli中的map数据类型获得了语法帮助。

SQS中的结果消息将属性作为消息的一部分显示:

{
  "Type" : "Notification",
  "MessageId" : "53e3adad-723a-5eae-a7b7-fc0468ec2d37",
  "TopicArn" : "arn:aws:sns:ap-southeast-2:123456789012:foo",
  "Subject" : "subj",
  "Message" : "msg",
  "Timestamp" : "2017-05-29T12:48:22.186Z",
  ...
  "MessageAttributes" : {
    "somename" : {"Type":"String","Value":"somevalue"}
  }
}

如果这些属性能够作为官方的SQS属性附加在消息中,那将会更好。但很遗憾,似乎并非如此。


我从你的回答中推断,目前没有办法让SNS以任何方式实际创建SQS属性。最有可能的添加SQS属性的方法是使用其中一个SDK或直接使用API,而不使用像SNS这样的服务。 - Evgeny
1
@Evgeny,没错。不幸的是,SNS/SQS集成不能以直观的方式处理消息属性。例如,您还可以使用SNS > Lambda > SQS,使用Lambda函数中的自定义代码从SNS消息属性中填充SQS消息属性。 - Michael - sqlbot
1
@Michael-sqlbot 已经在处理此问题了。似乎 CloudWatch Events SQS 目标也不支持 SQS _message attributes_,所以我正在处理此问题 :( - Evgeny
2
你是否忘记修改订阅属性RawMessageDelivery?默认情况下,它为false。以下是使用AWS CLI的示例:aws sns set-subscription-attributes --subscription-arn 'subscriptionarn' --attribute-name RawMessageDelivery --attribute-value true - Borys Generalov
8
这不是正确的答案。@BorysGeneralov在他的回答中得到了正确的答案:https://dev59.com/y1cP5IYBdhLWcg3wiqds#49753291 - Michael Oryl
如果您正在寻找快速解决方案,但不确定具体的方式,我必须使用此对象签名(network与我的项目业务规则相关): MessageAttributes: { network: { DataType: 'String', StringValue: messageBody.network, }, }, - A Mehmeto

3

如果您在这里是因为有一个已订阅SNS主题的SQS队列,您检查了您的订阅是否将原始消息传递设置为True,但仍然无法读取SQS消息上的属性:

请确保您的SQS客户端没有过滤掉消息属性。

以下代码只在从SQS队列接收消息时包括myAttribute

SQS.receiveMessage({
  QueueUrl: queueUrl,
  VisibilityTimeout: 20,
  WaitTimeSeconds: 10,
  MessageAttributeNames: [
    "myAttribute"
  ],
},...

如果您想读取除了myAttribute以外的某些属性值,您将需要指定它们(白名单)或将"myAttribute"替换为"All"来包含所有SQS属性。

SQS.receiveMessage({
  MessageAttributeNames: [
    "myAttribute", "myOtherAttribute"
  ],
},...

参考文献:https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html


2

在为SNS内的主题添加SQS订阅时启用原始消息传递类型


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接