我将从如何描述我的应用程序开始。
如果我网站上的用户添加任务,则该任务被分解为多个子任务,数量可以从1到10个任务变化。 这10个任务被添加到SQS队列中。 我有一个运行node.js和docker的Ubuntu EC2实例。
Node.js被configuration为侦听队列,一旦它接收到子任务消息,它就会产生一个Docker容器,它将执行子任务。 一旦子任务完成,容器被销毁。
我有一个c4.2xlarge的EC2实例,可以完美地执行上述过程,完成1个任务(10个子任务)。 然而,当多个任务同时被添加时,问题就出现了。 假设我对10个任务进行了testing,这些任务被分解为100个子任务,服务器在启动容器期间经历了严重的负载。
我如何去扩展这样的环境?
我一直在考虑保留一个停止的EC2实例池,是“停止”,因为产生新实例的延迟非常高,我想尽快消耗队列中的子任务,而不必承担全天候运行服务器的成本。
在node.js中写入负载平衡器是基于队列中的资源/消息数量的最佳方式吗?
您不需要负载平衡器。 您需要调整应用程序处理队列中项目的方式。
基于各种实例大小对应用程序进行基准testing,以确定它可以同时处理的最佳/最大数量的任务。 为了说明的目的,我们假设这个数字是20。
更改您的应用程序,从队列中拉出最多20个项目,从来没有更多。 当你的20个子任务中的一个完成时,它可以返回到更多的队列。
此时,您的单个工作服务器不应“超载”。 这将需要一段时间,通过大量的项目工作。
你需要有这样的限制,以防止你的“容器启动过程中的严重负载”。
一旦你有了这个,你可以做一些优化:
你需要每次产生新的容器,还是可以重新使用它们? 这将在处理子任务时节省一些CPU周期。
您可以在停止状态下使用EC2实例,而不是产生新的实例。 但是,您必须自定义处理您的CloudWatch警报,但可以完成。 您希望SNS上的侦听器等待警报,在此时可以根据需要启动和停止EC2实例。
使用各种实例大小对应用程序进行基准testing 有可能使用两个c4.xlarge比使用一个c4.2xlarge要好。 试验并尝试不同的组合。