基于 Amazon SQS 的扩缩策略
重要
以下信息和步骤向您展示了如何在将每个实例的 Amazon SQS 队列积压作为自定义指标发布到 CloudWatch 前使用 ApproximateNumberOfMessages 队列属性计算它。但是,您现在可以使用指标数学来节省发布自己的指标所花费的成本和精力。有关更多信息,请参阅 使用指标数学创建目标跟踪扩缩策略。
您可以扩展自动扩缩组以响应 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 CLI 或 开发工具包将自定义指标发布到 CloudWatch。然后,您可以使用 Amazon Web Services 管理控制台 监控指标。
在以下各节中为需要执行的任务使用 Amazon CLI。例如,要获取反映队列当前使用情况的指标数据,请使用 SQS get-queue-attributes
Amazon SQS 和实例缩减保护
实例被终止时还未处理的消息将返回 SQS 队列中,可由仍在运行的实例进行处理。对于执行长时间运行任务的应用程序,您可以选择使用实例扩展保护来控制 Auto Scaling 组扩展时终止哪些队列工作程序。
以下伪代码显示了保护长时间运行、队列驱动的工件进程免受缩放终止的一种方法。
while (true) { SetInstanceProtection(False); Work = GetNextWorkUnit(); SetInstanceProtection(True); ProcessWorkUnit(Work); SetInstanceProtection(False); }
有关更多信息,请参阅 设计您的应用程序以妥善处理实例终止。