Amazon Simple Notification Service
开发人员指南 (API Version 2010-03-31)
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。请点击 Amazon AWS 入门,可查看中国地区的具体差异

使用 Amazon SNS 筛选消息

默认情况下,Amazon SNS 主题的订阅者会收到发布到该主题的所有消息。若要仅接收一部分消息,订阅者可将筛选策略分配给主题订阅。

筛选策略是简单的 JSON 对象。该策略包含定义订阅者将收到的消息的属性。当您将一条消息发布到某个主题时,Amazon SNS 会比较该消息的属性与该主题的每个订阅的筛选策略中的属性。如果属性之间存在匹配项,Amazon SNS 则将消息发送给订阅者。否则,Amazon SNS 跳过订阅者而不向其发送消息。

使用筛选策略后,您可以通过将消息筛选条件合并到主题订阅中来简化对 Amazon SNS 的使用。通过此合并,您可以从订阅者卸载消息筛选逻辑,从发布者卸载消息路由逻辑。这样,就不需要通过为每个筛选条件创建单独的主题来筛选消息。相反,您可以使用单个主题,并用属性来区分消息。每个订阅者只收到并处理其筛选策略所接受的消息。

例如,您可以使用单个主题来发布由您的零售网站上的事务生成的所有消息。对于每条消息,您可以分配一个属性来指示事务类型,如 order_placedorder_cancelledorder_declined。通过使用筛选策略来创建订阅,可以将每条消息路由到用于处理该消息的事务类型的队列。

订阅筛选策略

可以将筛选策略分配给 Amazon SNS 订阅。在一条策略中,可以指定属性名称,同时对于每个名称,可以分配一个值或多个值的列表。只有当消息包含的属性与订阅的筛选策略中指定的特性相匹配时,订阅才接受消息。具体来说,只有符合以下条件时,订阅才接受消息:

  1. 筛选策略中的每个属性名均与分配给消息的一个属性名匹配。

  2. 对于每个匹配的属性名,在筛选策略和消息中分配给该名称的值之间至少存在一个匹配项。

当 Amazon SNS 对照策略评估消息属性时,它会忽略在策略中未指定的消息属性。

创建筛选策略时,请记住以下约束:

  • Amazon SNS 仅将策略属性与数据类型为 StringString.Array 的消息属性进行比较。数据类型为 NumberBinary 的消息属性被忽略。

  • 策略和消息之间的属性比较区分大小写。

  • 作为 JSON 对象,筛选策略可以包含用引号括起来的字符串、数字和无引号关键字 truefalsenull

  • 数字按字符串来比较,因此数字 300、300.0 和 3.0e2 不相等。

  • 一个筛选策略最多可以具有 10 个属性名称。

  • 策略的最大大小为 256 KB.

  • 策略必须为有效的 UTF-8 字符串。

下面的示例演示筛选策略如何接受或拒绝发布到主题的消息。

包含属性的消息示例

下面的示例演示由发布客户事务记录的 Amazon SNS 主题所发送的消息负载。该消息包括描述事务的属性:商店名称、事件类型和下单客户所指定的兴趣:

{ "Type" : "Notification", "MessageId" : "e3c4e17a-819b-5d95-a0e8-b306c25afda0", "TopicArn" : "arn:aws:sns:us-east-1:111122223333:MySnsTopic", "Message" : message body with transaction details . . . "Timestamp" : "2017-11-07T23:28:01.631Z", "SignatureVersion" : "1", "Signature" : signature . . . "UnsubscribeURL" : unsubscribe URL . . . "MessageAttributes" : { "customer_interests" : {"Type":"String.Array","Value":"[\"soccer\", \"rugby\", \"hockey\"]"}, "store" : {"Type":"String","Value":"example_corp"}, "event" : {"Type":"String","Value":"order_placed"} } }

有关将属性应用到消息的信息,请参阅 使用 Amazon SNS 消息属性

由于此消息包含属性,因此,任何包含筛选策略的主题订阅均可选择接收或拒绝此消息。

接受示例消息的筛选策略

下面的策略接受示例消息,因为策略中的属性名称和值与分配给消息的匹配:

{ "store": ["example_corp"], "event": ["order_placed"] }

以下策略包含多个属性值。该策略接受示例消息,因为至少有一个值 (rugby) 与分配给消息属性中的 customer_interests 的值匹配:

{ "customer_interests": ["rugby", "football", "baseball"] }

拒绝示例消息的筛选策略

以下策略拒绝示例消息,因为策略和消息属性之间不匹配。

在以下策略中,属性值 order-cancelled 与分配给消息属性中的 event 的值不匹配:

{ "store": ["example_corp"], "event": ["order-cancelled"] }

以下策略包括属性名 encrypted,该属性名在消息属性中不存在:

{ "store": ["example_corp"], "event": ["order-placed"], "encrypted": [false] }

在以下策略中,值 basketballbaseball 与分配给消息属性中的 customer_interests 的值都不匹配:

{ "customer_interests": ["basketball", "baseball"] }

应用订阅筛选策略

您可以使用 Amazon SNS 控制台将筛选策略应用于 Amazon SNS 订阅。或者,如果以编程方式应用策略,则可以使用 Amazon SNS API、AWS Command Line Interface (AWS CLI) 或任何支持 Amazon SNS 的 AWS 软件开发工具包,如 AWS SDK for Java。

使用控制台应用筛选策略

使用 Amazon SNS 控制台完成以下应用筛选策略的步骤:

  1. 通过以下网址登录 AWS 管理控制台 并打开 Amazon SNS 控制台:https://console.amazonaws.cn/sns/v2/home

  2. 在导航窗格中,选择 SubscriptionsSubscriptions 页面提供您在所选区域具有的所有 Amazon SNS 订阅。

  3. 如果您没有订阅,则选择 Create subscription,并为 Topic ARNProtocolEndpoint 提供值。

  4. 如果您有一个或多个订阅,请选择要向其应用筛选策略的订阅。

  5. 选择 Actions,并在菜单中选择 Edit subscription filter policy

  6. Edit subscription filter policy 窗口中,提供筛选策略的 JSON 正文。

  7. 选择 Set subscription filter policy。Amazon SNS 将您的筛选策略应用到订阅。

使用 AWS CLI 应用筛选策略

要使用 AWS Command Line Interface (AWS CLI) 应用筛选策略,请使用 set-subscription-attributes 命令,如以下示例中所示:

$ aws sns set-subscription-attributes --subscription-arn arn:aws:sns: ... --attribute-name FilterPolicy --attribute-value '{"store":["example_corp"],"event":["order_placed"]}'

对于 --attribute-name 选项,请指定 FilterPolicy。对于 --attribute-value,请指定您的 JSON 策略。

要为您的策略提供有效的 JSON,请用双引号将属性名和值括起来。此外,您必须用引号将整个策略参数括起来。要避免转义引号,您可以使用单引号将策略括起来,并使用双引号将 JSON 名称和值括起来,如示例中所示。

要验证是否已应用您的筛选策略,请使用 get-subscription-attributes 命令。终端输出中的属性应显示 FilterPolicy 键的筛选策略,如以下示例中所示:

$ aws sns get-subscription-attributes --subscription-arn arn:aws:sns: ... { "Attributes": { "Endpoint": "endpoint . . .", "Protocol": "https", "RawMessageDelivery": "false", "EffectiveDeliveryPolicy": "delivery policy . . .", "ConfirmationWasAuthenticated": "true", "FilterPolicy": "{\"store\": [\"example_corp\"], \"event\": [\"order_placed\"]}", "Owner": "111122223333", "SubscriptionArn": "arn:aws:sns: . . .", "TopicArn": "arn:aws:sns: . . ." } }

使用 适用于 Java 的开发工具包 应用筛选策略

要使用 AWS SDK for Java 应用筛选策略,请使用 AmazonSNS 客户端的 setSubscriptionAttributes 方法。提供 SetSubscriptionAttributesRequest 对象作为参数,如以下示例所示:

AmazonSNS snsClient = AmazonSNSClientBuilder.defaultClient(); String filterPolicyString = "{\"store\":[\"example_corp\"],\"event\":[\"order_placed\"]}"; SetSubscriptionAttributesRequest request = new SetSubscriptionAttributesRequest(subscriptionArn, "FilterPolicy", filterPolicyString); snsClient.setSubscriptionAttributes(request);

要初始化 SetSubscriptionAttributesRequest 对象,请提供以下参数:

  • subscriptionArn – 要向其应用策略的订阅的 Amazon 资源名称 (ARN)。

  • attributeName – 必须为 "FilterPolicy"

  • attributeValue – 字符串形式的 JSON 筛选策略。因为您必须用双引号将字符串策略括起来,所以请记住对括起属性名称和值的双引号进行转义,如 \"store\" 中所示。

SetSubscriptionAttributesRequest 类接受筛选策略作为字符串。如果要将策略定义为 Java 集合,请创建一个映射来将每个属性名称与一个值列表相关联。若要将策略分配给订阅,首先要从映射的内容生成策略的字符串版本,然后将该字符串作为 attributeValue 参数传递给 SetSubscriptionAttributesRequest

为了简化此流程,您可以向应用程序添加以下示例类并根据需要修改它:

import com.amazonaws.services.sns.AmazonSNS; import com.amazonaws.services.sns.model.SetSubscriptionAttributesRequest; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; public class SNSMessageFilterPolicy { private Map<String, ArrayList<String>> filterPolicy; public SNSMessageFilterPolicy() { filterPolicy = new HashMap<>(); } public void setFilterPolicy(Map<String, ArrayList<String>> filterPolicy) { this.filterPolicy = filterPolicy; } public Map<String, ArrayList<String>> getFilterPolicy() { return filterPolicy; } public <T> void addAttribute(String attributeName, T attributeValue) { ArrayList<T> attributeValueArray = new ArrayList<>(); attributeValueArray.add(attributeValue); addAttribute(attributeName, attributeValueArray); } public void addAttribute(String attributeName, ArrayList<?> attributeValues) { ArrayList<String> attributeValueStrings = new ArrayList<>(); for (Object o : attributeValues) { attributeValueStrings.add(o.toString()); } filterPolicy.put(attributeName, attributeValueStrings); } public void apply(AmazonSNS snsClient, String subscriptionArn) { SetSubscriptionAttributesRequest request = new SetSubscriptionAttributesRequest(subscriptionArn, "FilterPolicy", formatFilterPolicy()); snsClient.setSubscriptionAttributes(request); } public String formatFilterPolicy() { return filterPolicy.entrySet() .stream() .map(entry -> "\"" + entry.getKey() + "\": " + entry.getValue() .stream() .collect(Collectors.joining("\", \"", "[\"", "\"]"))) .collect(Collectors.joining(", ", "{", "}")); } }

该类存储 filterPolicy 字段作为映射。您可以使用重载 addAttribute 方法将属性添加到策略。这些方法接受属性名称作为字符串,并且接受属性值作为单个通用项或通用项列表。因为这些值是通用的,所以您可以添加字符串或基元类型的值 (例如 "rugby"1false)。当您准备将策略应用于订阅时,请使用 apply 方法,并提供一个 AmazonSNS 客户端和订阅 ARN。该方法从 filterPolicy 映射的内容生成策略字符串,并且将策略应用于指定的订阅。

下面的代码演示如何初始化和使用示例 SNSMessageFilterPolicy 类:

// Initialize example filter policy class SNSMessageFilterPolicy fp = new SNSMessageFilterPolicy(); // Add filter policy attribute with single value fp.addAttribute("store", "example_corp"); fp.addAttribute("event", "order_placed"); // Add filter policy attribute with a list of values ArrayList<String> attributeValues = new ArrayList<>(); attributeValues.add("rugby"); attributeValues.add("soccer"); attributeValues.add("hockey"); fp.addAttribute("customer_interests", attributeValues); // Add filter policy attribute with primitive value (boolean in this case) fp.addAttribute("encrypted", false); // Apply filter policy attributes to SNS subscription fp.apply(snsClient, subscriptionArn);

使用 Amazon SNS API 应用筛选策略

要使用 Amazon SNS API 应用筛选策略,需要请求 SetSubscriptionAttributes 操作。将 AttributeName 参数设置为 FilterPolicy,并将 AttributeValue 参数设置为您的筛选策略 JSON。