根据 Amazon SQS 进行扩展 - Amazon EC2 Auto Scaling
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

根据 Amazon SQS 进行扩展

本节介绍如何扩展 Auto Scaling 组以响应 Amazon Simple Queue Service (Amazon SQS) 队列中系统负载的变化。要了解有关如何使用 Amazon SQS 的更多信息,请参阅 Amazon 简单队列服务开发人员指南

在一些情况下,您可能会考虑根据 Amazon SQS 队列中的活动扩展。例如,假设您有 Web 应用程序,让用户上传图像并联机使用。在此场景中,每个图像需要先调整大小并编码,然后才能发布。该应用程序在 Auto Scaling 组中的 EC2 实例上运行,配置为处理您的典型上传速率。不正常的实例将终止并进行替换,以始终保持当前的实例等级。该应用程序将图像的原始位图数据放在 SQS 队列中以进行处理。它处理这些图像,然后将处理的图像发布到某个位置以供用户查看。如果上传的图像数不随时间波动,则适用于此场景的架构可以良好运作。但是,如果上传数量随着时间波动,您可以考虑使用动态扩展来缩放 Auto Scaling 组的容量。

将目标跟踪与合适的指标结合使用

如果您使用基于自定义 Amazon SQS 队列指标的目标跟踪扩展策略,则动态扩展可以更有效地适应应用程序的需求曲线。有关为目标跟踪选择指标的更多信息,请参阅 选择指标

为目标跟踪使用 CloudWatch Amazon SQS 指标(例如 ApproximateNumberOfMessagesVisible)的问题是,队列中的消息数,可能不会随着处理队列中消息的 Auto Scaling 组的大小按比例发生变化。这是因为 SQS 队列中的消息数不仅仅定义所需的实例数。Auto Scaling 组中的实例数可能由多种因素决定,包括处理消息所需的时间以及可接受的延迟长度(队列延迟)。

该解决方案使用要维护的每个实例的积压 指标以及每个实例的可接受积压 的目标值。您可以按以下所示计算这些数字:

  • 每个实例的积压:要计算您每个实例的积压,首先通过 ApproximateNumberOfMessages 度列属性确定 SQS 队列的长度(可从队列中检索的消息数)。将该数字除以队列的运行容量(对于 Auto Scaling 组,这是处于 InService 状态的实例数量),以获得每个实例的积压。

  • 每个实例的可接受积压:要计算您的目标值,请先确定您的应用程序可以接受的延迟。然后,将可接受的延迟值除以 EC2 实例处理一条消息所用的平均时间。

例如,假设您当前有一个包含 10 个实例的自动扩缩组,并且队列中的可见消息数量(ApproximateNumberOfMessages)是 1500。如果每条消息的平均处理时间为 0.1 秒,最长可接受延迟为 10 秒,则每个实例的可接受积压为 10/0.1,即 100 条消息。这意味着您的目标跟踪策略的目标值为 100。当每个实例的积压达到目标值时,将发生横向扩展事件。由于每个实例已经积压了 150 条消息(10 个实例 1500 条消息),该组会横向扩展并增加了 5 个实例以维持与目标值的比例。

以下过程演示如何发布自定义指标和创建目标跟踪扩展策略,以根据这些计算值来配置您的 Auto Scaling 组进行扩展。

此配置有三个主要部分:

  • 一个 Auto Scaling 组,用于管理处理来自 SQS 队列的消息的 EC2 实例。

  • 一个发送到 Amazon CloudWatch 的自定义指标,用于衡量 Auto Scaling 组中每个 EC2 实例的队列的消息数。

  • 一个目标跟踪策略,配置您的 Auto Scaling 组根据自定义指标和设定的目标值进行扩展。CloudWatch 警报调用该扩展策略。

下图演示了此配置的架构。


                        Amazon EC2 Auto Scaling 使用队列架构图

限制和先决条件

要使用此配置,您需要注意以下限制:

  • 您必须使用 Amazon CLI 或 开发工具包将自定义指标发布到 CloudWatch。然后,您可以使用 Amazon Web Services Management Console 监控指标。

  • 发布自定义指标后,您必须通过 Amazon CLI 或 SDK,创建使用自定义指标规范的目标跟踪扩展策略

以下各节指示您为需要执行的任务使用 Amazon CLI。例如,要获取反映队列当前使用情况的指标数据,请使用 SQS get-queue-attributes 命令。确保您已经安装并配置 CLI。

开始之前,您必须有一个要使用的 Amazon SQS 队列。以下部分假设您已经有一个队列(标准队列或 FIFO 队列)、一个 Auto Scaling 组以及 EC2 实例(运行使用队列的应用程序)。有关 Amazon SQS 权限的更多信息,请参阅 Amazon 简单队列服务开发人员指南

配置基于 Amazon SQS 的缩放

步骤 1:创建 CloudWatch 自定义指标

自定义指标是使用您选择的指标名称和命名空间定义的。自定义指标的命名空间不能以 AWS/ 开头。有关发布自定义指标的更多信息,请参阅 Amazon CloudWatch 用户指南中的发布自定义指标主题。

按照此过程,通过首先从您的 Amazon 账户读取信息来创建自定义指标。然后,计算前面的章节中建议的每个实例的积压指标。最后,按照 1 分钟的粒度将该数字发布到 CloudWatch。只要可能,我们强烈建议您按 1 分钟粒度的指标进行扩展,以确保更快地响应系统负载变化。

要创建 CloudWatch 自定义指标

  1. 使用 SQS get-queue-attributes 命令获取在队列中等待的消息数 (ApproximateNumberOfMessages)。

    aws sqs get-queue-attributes --queue-url https://sqs.region.amazonaws.com/123456789/MyQueue \ --attribute-names ApproximateNumberOfMessages
  2. 使用 describe-auto-scaling-groups 命令获取组的运行容量,这是处于 InService 生命周期状态的实例数。此命令返回 Auto Scaling 组的实例及其生命周期状态。

    aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names my-asg
  3. 将该队列中可供检索的大致消息数量除以该组的运行容量,计算得出每个实例的积压。

  4. 按照 1 分钟的粒度将结果发布为 CloudWatch 自定义指标。

    以下是示例 CLI put-metric-data 命令:

    aws cloudwatch put-metric-data --metric-name MyBacklogPerInstance --namespace MyNamespace \ --unit None --value 20 --dimensions MyOptionalMetricDimensionName=MyOptionalMetricDimensionValue

应用程序发出所需的指标之后,数据发送到 CloudWatch。该指标会显示在 CloudWatch 控制台中。您可以登录到 Amazon Web Services Management Console 并导航到 CloudWatch 页面来访问它。然后,通过导航到指标页面或者使用搜索框搜索指标来查看指标。有关查看指标的更多信息,请参阅 Amazon CloudWatch 用户指南 中的查看可用指标

步骤 2:创建目标跟踪扩展策略

发布自定义指标后,使用自定义指标规范创建目标跟踪扩展策略

创建目标跟踪扩展策略

  1. 使用以下命令可以在您的主目录的 config.json 文件中为扩展策略指定目标值。

    对于 TargetValue,计算每个实例的可接受积压指标并在此处输入。要计算此数值,请考虑正常延迟值并将其除以处理一条消息所需的平均时间。

    $ cat ~/config.json { "TargetValue":100, "CustomizedMetricSpecification":{ "MetricName":"MyBacklogPerInstance", "Namespace":"MyNamespace", "Dimensions":[ { "Name":"MyOptionalMetricDimensionName", "Value":"MyOptionalMetricDimensionValue" } ], "Statistic":"Average", "Unit":"None" } }
  2. 使用 put-scaling-policy 命令以及在之前步骤中创建的 config.json 文件来创建扩展策略:

    aws autoscaling put-scaling-policy --policy-name sqs100-target-tracking-scaling-policy \ --auto-scaling-group-name my-asg --policy-type TargetTrackingScaling \ --target-tracking-configuration file://~/config.json

    这会创建两个警报:一个用于增加实例数量,另一个用于减少实例数量。它还将返回注册到 CloudWatch 的策略的 Amazon 资源名称(ARN),CloudWatch 使用该名称在超过指标阈值的任何时候调用扩缩。

步骤 3:测试扩展策略

在您完成设置后,验证您的扩展策略是否正常工作。您可以通过以下方式测试:增加 SQS 队列中的消息数,然后验证 Auto Scaling 组是否已启动更多 EC2 实例。您还可以通过以下方式测试:减少 SQS 队列中的消息数,然后验证 Auto Scaling 组是否终止了一个 EC2 实例。

测试扩展函数

  1. 按照教程:将消息发送到 Amazon SQS 队列中的步骤将消息添加到队列。请确保您增加了队列中的消息数量,使得每个实例的积压指标超过目标值。

    您的更改调用警报可能需要几分钟时间。

  2. 使用 describe-auto-scaling-groups 命令验证该组是否已启动了实例:

    aws autoscaling describe-auto-scaling-groups --auto-scaling-group-name my-asg

测试缩减函数

  1. 按照教程:将消息发送到 Amazon SQS 队列中的步骤从队列中删除消息。请确保您减少了队列中的消息数量,使得每个实例的积压指标低于目标值。

    您的更改调用警报可能需要几分钟时间。

  2. 使用 describe-auto-scaling-groups 命令验证该组是否已终止了实例:

    aws autoscaling describe-auto-scaling-groups --auto-scaling-group-name my-asg

Amazon SQS 和实例缩减保护

实例被终止时还未处理的消息将返回 SQS 队列中,可由仍在运行的实例进行处理。对于执行长时间运行任务的应用程序,您可以选择使用实例扩展保护来控制 Auto Scaling 组扩展时终止哪些队列工作程序。

以下伪代码显示了保护长时间运行、队列驱动的工件进程免受缩放终止的一种方法。

while (true) { SetInstanceProtection(False); Work = GetNextWorkUnit(); SetInstanceProtection(True); ProcessWorkUnit(Work); SetInstanceProtection(False); }

有关更多信息,请参阅 实例横向缩减保护