

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 Amazon SNS 中应用订阅筛选策略
<a name="message-filtering-apply"></a>

利用 Amazon SNS 中的消息筛选，您可以根据筛选策略有选择地向订阅用户传送消息。这些策略定义了发送到订阅的消息必须满足的条件。虽然原始消息传送是一个可能影响消息处理的选项，但订阅筛选无需该选项即可运行。

您可以使用 Amazon SNS 控制台将筛选策略应用于 Amazon SNS 订阅。或者，要以编程方式应用策略，您可以使用亚马逊 SNS API、 AWS Command Line Interface AWS CLI() 或 AWS 任何支持 Amazon SNS 的软件开发工具包。你也可以使用 AWS CloudFormation。

**实现原始消息传输**

原始消息交付可确保消息有效载荷按原样交付给订阅用户，而无需进行任何额外的编码或转换。当订阅用户需要使用原始消息格式进行处理时，这可能很有用。但是，原始消息的传送与订阅筛选的功能没有直接关系。

**应用订阅筛选**

要将消息筛选应用于订阅，请使用 JSON 语法定义筛选策略。该策略规定了消息必须满足什么条件才能发送到订阅中。筛选可以基于消息属性，例如消息属性、消息结构甚至消息内容。

**原始消息传送和订阅筛选之间的关系**

虽然启用原始消息传送会影响订阅用户传递和处理消息的方式，但这并不是使用订阅筛选的先决条件。但是，在订阅用户需要原始消息格式而不做任何修改的情况下，启用原始消息传送可能会与订阅筛选一起发挥作用。

**有效筛选的注意事项**

在实现消息过滤时，请考虑您的应用程序和订阅用户的特定要求。定义与消息传送标准精确匹配的筛选策略，以确保高效、有针对性的消息分发。

**重要**  
AWS 诸如 IAM 和 Amazon SNS 之类的服务使用一种称为最终一致性的分布式计算模型。对订阅筛选器策略的添加或更改最多需要 15 分钟即可完全生效。

## AWS 管理控制台
<a name="message-filtering-apply-console"></a>

1. 登录 [Amazon SNS 控制台](https://console.aws.amazon.com/sns/home)。

1. 在导航面板中，选择**订阅**。

1. 选择订阅，然后选择**编辑**。

1. 在 **Edit**（编辑）页面上，展开 **Subscription filter policy**（订阅筛选策略）部分。

1. 在 **attribute-based filtering**（基于属性的筛选）或 **payload-based filtering**（基于有效负载的筛选）之间进行选择。

1. 在 **JSON editor**（JSON 编辑器）字段中，提供筛选策略的 **JSON body**（JSON 正文）。

1. 选择 **Save changes**（保存更改）。

   Amazon SNS 将您的筛选策略应用到订阅。

## AWS CLI
<a name="message-filtering-apply-cli"></a>

要使用 AWS Command Line Interface (AWS CLI) 应用筛选策略，请使用[https://docs.aws.amazon.com/cli/latest/reference/sns/set-subscription-attributes.html](https://docs.aws.amazon.com/cli/latest/reference/sns/set-subscription-attributes.html)命令，如以下示例所示。对于 `--attribute-name` 选项，请指定 `FilterPolicy`。对于 `--attribute-value`，请指定您的 **JSON policy**（JSON 策略）。

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

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

如果要从基于属性（默认）的邮件筛选切换到基于负载的邮件过滤，也可以使用该[set-subscription-attributes](https://docs.aws.amazon.com/cli/latest/reference/sns/set-subscription-attributes.html)命令。对于 `--attribute-name` 选项，请指定 `FilterPolicyScope`。对于 `--attribute-value`，请指定 `MessageBody`。

```
$ aws sns set-subscription-attributes --subscription-arn arn:aws:sns: ... --attribute-name FilterPolicyScope --attribute-value MessageBody
```

要验证是否已应用您的筛选策略，请使用 `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\"]}", 
        "FilterPolicyScope": "MessageAttributes",
        "Owner": "111122223333", 
        "SubscriptionArn": "arn:aws:sns: . . .", 
        "TopicArn": "arn:aws:sns: . . ."
    }
}
```

## AWS SDKs
<a name="message-filtering-apply-sdks"></a>

以下代码示例演示如何使用 `SetSubscriptionAttributes`。

**重要**  
如果您使用 SDK for Java 2.x 示例，则类 `SNSMessageFilterPolicy` 并非开箱即用。有关如何安装该类的说明，请参阅 GitHub 网站上的[示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/sns/src/main/java/com/example/sns/SNSMessageFilterPolicy.java)。

------
#### [ CLI ]

**AWS CLI**  
**设置订阅属性**  
以下 `set-subscription-attributes` 示例将 `RawMessageDelivery` 属性设置为 SQS 订阅。  

```
aws sns set-subscription-attributes \
    --subscription-arn {{arn:aws:sns:us-east-1:123456789012:mytopic:f248de18-2cf6-578c-8592-b6f1eaa877dc}} \
    --attribute-name {{RawMessageDelivery}} \
    --attribute-value {{true}}
```
此命令不生成任何输出。  
以下 `set-subscription-attributes` 示例将 `FilterPolicy` 属性设置为 SQS 订阅。  

```
aws sns set-subscription-attributes \
    --subscription-arn {{arn:aws:sns:us-east-1:123456789012:mytopic:f248de18-2cf6-578c-8592-b6f1eaa877dc}} \
    --attribute-name {{FilterPolicy}} \
    --attribute-value "{ \"anyMandatoryKey\": [\"any\", \"of\", \"these\"] }"
```
此命令不生成任何输出。  
以下 `set-subscription-attributes` 示例从 SQS 订阅中移除 `FilterPolicy` 属性。  

```
aws sns set-subscription-attributes \
    --subscription-arn {{arn:aws:sns:us-east-1:123456789012:mytopic:f248de18-2cf6-578c-8592-b6f1eaa877dc}} \
    --attribute-name {{FilterPolicy}} \
    --attribute-value {{"{}"}}
```
此命令不生成任何输出。  
+  有关 API 的详细信息，请参阅*AWS CLI 命令参考[SetSubscriptionAttributes](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sns/set-subscription-attributes.html)*中的。

------
#### [ Java ]

**适用于 Java 的 SDK 2.x**  
 还有更多相关信息 GitHub。在 [AWS 代码示例存储库](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/sns#code-examples)中查找完整示例，了解如何进行设置和运行。

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.SnsException;
import java.util.ArrayList;

/**
 * Before running this Java V2 code example, set up your development
 * environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */
public class UseMessageFilterPolicy {
    public static void main(String[] args) {
        final String usage = """

                Usage:    <subscriptionArn>

                Where:
                   subscriptionArn - The ARN of a subscription.

                """;

        if (args.length != 1) {
            System.out.println(usage);
            System.exit(1);
        }

        String subscriptionArn = args[0];
        SnsClient snsClient = SnsClient.builder()
                .region(Region.US_EAST_1)
                .build();

        usePolicy(snsClient, subscriptionArn);
        snsClient.close();
    }

    public static void usePolicy(SnsClient snsClient, String subscriptionArn) {
        try {
            SNSMessageFilterPolicy fp = new SNSMessageFilterPolicy();
            // Add a filter policy attribute with a single value
            fp.addAttribute("store", "example_corp");
            fp.addAttribute("event", "order_placed");

            // Add a prefix attribute
            fp.addAttributePrefix("customer_interests", "bas");

            // Add an anything-but attribute
            fp.addAttributeAnythingBut("customer_interests", "baseball");

            // Add a 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 a numeric attribute
            fp.addAttribute("price_usd", "=", 0);

            // Add a numeric attribute with a range
            fp.addAttributeRange("price_usd", ">", 0, "<=", 100);

            // Apply the filter policy attributes to an Amazon SNS subscription
            fp.apply(snsClient, subscriptionArn);

        } catch (SnsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
}
```
+  有关 API 的详细信息，请参阅 *AWS SDK for Java 2.x API 参考[SetSubscriptionAttributes](https://docs.aws.amazon.com/goto/SdkForJavaV2/sns-2010-03-31/SetSubscriptionAttributes)*中的。

------
#### [ Python ]

**适用于 Python 的 SDK（Boto3）**  
 还有更多相关信息 GitHub。在 [AWS 代码示例存储库](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/python/example_code/sns#code-examples)中查找完整示例，了解如何进行设置和运行。

```
class SnsWrapper:
    """Encapsulates Amazon SNS topic and subscription functions."""

    def __init__(self, sns_resource):
        """
        :param sns_resource: A Boto3 Amazon SNS resource.
        """
        self.sns_resource = sns_resource


    @staticmethod
    def add_subscription_filter(subscription, attributes):
        """
        Adds a filter policy to a subscription. A filter policy is a key and a
        list of values that are allowed. When a message is published, it must have an
        attribute that passes the filter or it will not be sent to the subscription.

        :param subscription: The subscription the filter policy is attached to.
        :param attributes: A dictionary of key-value pairs that define the filter.
        """
        try:
            att_policy = {key: [value] for key, value in attributes.items()}
            subscription.set_attributes(
                AttributeName="FilterPolicy", AttributeValue=json.dumps(att_policy)
            )
            logger.info("Added filter to subscription %s.", subscription.arn)
        except ClientError:
            logger.exception(
                "Couldn't add filter to subscription %s.", subscription.arn
            )
            raise
```
+  有关 API 的详细信息，请参阅适用[SetSubscriptionAttributes](https://docs.aws.amazon.com/goto/boto3/sns-2010-03-31/SetSubscriptionAttributes)于 *Python 的AWS SDK (Boto3) API 参考*。

------
#### [ SAP ABAP ]

**适用于 SAP ABAP 的 SDK**  
 还有更多相关信息 GitHub。在 [AWS 代码示例存储库](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/sap-abap/services/sns#code-examples)中查找完整示例，了解如何进行设置和运行。

```
    TRY.
        lo_sns->setsubscriptionattributes(
            iv_subscriptionarn = iv_subscription_arn
            iv_attributename  = 'FilterPolicy'
            iv_attributevalue = iv_filter_policy ).
        MESSAGE 'Added filter policy to subscription.' TYPE 'I'.
      CATCH /aws1/cx_snsnotfoundexception.
        MESSAGE 'Subscription does not exist.' TYPE 'E'.
    ENDTRY.
```
+  有关 API 的详细信息，请参阅适用[SetSubscriptionAttributes](https://docs.aws.amazon.com/sdk-for-sap-abap/v1/api/latest/index.html)于 S *AP 的AWS SDK ABAP API 参考*。

------

## Amazon SNS API
<a name="message-filtering-apply-api"></a>

要使用 Amazon SNS API 应用筛选策略，需要请求 [https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html](https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html) 操作。将 `AttributeName` 参数设置为 `FilterPolicy`，并将 `AttributeValue` 参数设置为您的筛选策略 JSON。

如果要从基于属性（默认）的消息筛选切换到基于有效负载的消息筛选，您也可以使用 [https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html](https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html) 操作。将 `AttributeName` 参数设置为 `FilterPolicyScope`，并将 `AttributeValue` 参数设置为 `MessageBody`。

## AWS CloudFormation
<a name="message-filtering-apply-cloudformation"></a>

要使用应用筛选策略 CloudFormation，请使用 JSON 或 YAML 模板创建 CloudFormation 堆栈。有关更多信息，请参阅《*AWS CloudFormation 用户指南》*中的`AWS::SNS::Subscription`资源[`FilterPolicy`属](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html#cfn-sns-subscription-filterpolicy)性和[示例 CloudFormation 模板](https://github.com/aws-samples/aws-sns-samples/blob/master/templates/SNS-Subscription-Attributes-Tutorial-CloudFormation.template)。

1. 登录 [CloudFormation 控制台](https://console.aws.amazon.com/cloudformation)。

1. 选择**创建堆栈**。

1. 在**选择模板**页面上，依次选择**将模板上传到 Amazon S3**、您的文件和**下一步**。

1. 在**指定详细信息**页面中，执行以下操作：

   1. 对于**堆栈名称**，键入 `MyFilterPolicyStack`。

   1. 对于 **myHttpEndpoint**，键入要订阅您的主题的 HTTP 终端节点。
**提示**  
如果没有 HTTP 终端节点，请创建一个。

1. 在**选项**页面上，选择**下一步**。

1. 在 **Review** 页面上，选择 **Create **。