根据 EC2 实例负载和 SQS 自动扩展 Docker 容器

根据 EC2 实例负载和 SQS 自动扩展 Docker 容器

我将首先简要描述一下我的应用程序的工作原理。

如果我网站上的用户添加了一个任务,该任务将被分解为多个子任务,数量从 1 到 10 个不等。这 10 个任务将添加到 SQS 队列中。我有一个运行 node.js 和 docker 的 Ubuntu EC2 实例。

Node.js 配置为监听队列,一旦收到子任务消息,它就会生成一个 docker 容器,然后执行子任务。一旦子任务完成,容器就会被销毁。

我有一个 c4.2xlarge EC2 实例,它可以完美地执行 1 个任务(10 个子任务)的上述过程。但是,当同时添加多个任务时,就会出现问题。假设我对 10 个任务进行测试,这些任务被分解为 100 个子任务,服务器在启动容器时会经历严重的负载。

我该如何扩展这样的环境?

我一直在考虑保留一个已停止的 EC2 实例池,是的“已停止”,因为生成新实例的延迟非常高,而且我想尽快使用队列中的子任务,而不必承担全天候运行服务器的成本。

根据队列中的资源/消息数量在 node.js 中编写负载均衡器是最好的方法吗?

答案1

你不需要负载均衡器。你需要调整应用程序处理队列中项目的方式。

  1. 针对各种实例大小对您的应用程序进行基准测试,以确定其可同时处理的最佳/最大任务数。为了便于说明,我们假设该数字为 20。

  2. 将您的应用程序更改为从队列中最多提取 20 个项目,不要超过。当您的 20 个子任务中的一个完成后,它可以返回队列以获取更多内容。

此时,您的单个工作服务器不应“超载”。它只是需要一段时间来处理大量项目队列。

您需要有这样的限制来防止“在启动容器期间产生严重负载”。

  1. 使用 CloudWatch 警报在队列过大时添加更多工作实例,并在队列变小时终止实例。每个实例一次将处理 20 个。

一旦你有了这个,你可以做一些优化:

  1. 每次都需要生成新容器吗?还是可以重复使用它们?这样可以在处理子任务时节省一些 CPU 周期。

  2. 您可能能够使用处于停止状态的 EC2 实例,而不是生成新实例。但您必须为此自定义处理 CloudWatch 警报,但这是可以做到的。您需要在 SNS 上有一个侦听器等待警报,此时它可以根据需要启动和停止 EC2 实例。

  3. 使用各种实例大小对您的应用程序进行基准测试。使用两个 c4.xlarge 可能比使用一个 c4.2xlarge 更好。尝试不同的组合。

答案2

现在可以通过无服务器技术、AWS Lambda 函数和 AWS SNS 或 SQS 来实现这一点。

https://aws.amazon.com/lambda/

例如,任务可以触发 SNS,然后将其发送到 Lambda,您的函数将根据需求自动扩展。

相关内容