【AICon】 如何构建高效的 RAG 系统?RAG 技术在实际应用中遇到的挑战及应对策略?>>> 了解详情
写点什么

基于 Amazon ECS 的并行批处理任务解决方案

  • 2019-10-22
  • 本文字数:5674 字

    阅读完需:约 19 分钟

基于 Amazon ECS 的并行批处理任务解决方案

很多企业都会有运行批处理任务的需求,而且这些批处理任务可能都是不同类型的工作,比如有的是处理数据的,有的是进行媒体编码的,有的是进行机器学习模型训练的。这些批处理任务通常都是通过消息进行触发,也就是说需要处理数据或者其他任务的时候,程序发起方会发送一个或者多个消息到一个特定的队列里,然后由监控该队列的应用程序发起任务处理。


本文描述了一种基于容器化的,在 Amazon ECS 平台上搭建的、并行批处理任务的、通用的解决方案。

解决方案概述

该方案如下图所示。



在该方案中,我们会启动一个 Amazon ECS 集群,并关联 auto scaling 组。然后在该平台上,我们可以借助一个开源工具:mapbox/watchbot(以下简称 watchbot)来搭建任务处理平台。该平台与 Amazon ECS 无缝集成,结合 Amazon ECR 和 ECS 服务,使得用户只需要关注任务处理程序即可,其他的任务调度,高可用性管理等工作,都可以由 watchbot 来完成。Watchbot 的处理流程如下图所示。



在使用 watchbot 之前,用户把自己的任务处理程序(可以是任何语言编写的程序)封装到 docker 镜像中,并上传到 Amazon ECR 里。然后在部署了 watchbot 以后,会在 Amazon ECS 集群里启动一个 ECS 服务,该服务会启动 1 到多个 watcher 容器(具体几个 watcher 容器可以由用户自己配置)。该 watcher 容器会监控一个预先创建好的 Amazon SQS 队列,一旦该队列里被放入了消息,watcher 容器就会把该消息设置为不可见,然后启动预先配置好的 ECS 任务或者也可以叫做任务容器(也就是上图中的蓝色方块),任务容器就会从 Amazon ECR 里拉取包含了用户业务处理程序的 docker 镜像,并把消息作为参数传给任务容器,然后在任务容器里根据传入的消息参数,进行相应的逻辑处理。任务容器执行完以后,可以有 4 种退出状态:


  1. 退出代码为 0:表示任务容器执行结束并正常退出,对应的消息会被 watcher 容器从队列里删除。

  2. 退出代码为 3:表示该消息被任务容器拒绝,对应的消息会被 watcher 容器从队列里删除,同时发送一个通知到 SNS 主题。

  3. 退出代码为 4:表示该消息不被任务容器处理,对应的消息会被 watcher 容器转移到对应的 error 队列。

  4. 退出代码为其他值:表示任务容器在处理该消息时发生被捕获的异常并主动退出,对应的消息会被 watcher 容器转移到对应的 error 队列,并发送一个通知到 SNS 主题。


如果任务容器在执行过程中出现未被捕获的故障而导致异常退出,则 watcher 容器会再次启动该任务容器,如果任务容器反复执行失败导致异常退出,则 watcher 容器在尝试一定次数以后,会放弃并把该消息放入对应的 error 队列。

架构部署

我们以 us-east-1 region 为例,一步一步的说明如何部署整个并行批处理任务解决方案。注意在部署之前,需要在你的电脑上配置 AWS credentials,并具有管理 Amazon ECR 和 Amazon ECS 的权限。或者也可以在一台 EC2 实例上完成部署工作,那么可以在该 EC2 实例上关联一个角色,并为角色赋予管理 Amazon ECR 和 ECS 的权限。


  1. 创建 Amazon ECS 集群,具体步骤参考:

  2. https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create_cluster.html。

  3. 该 ECS 集群可以与 Auto scaling 组结合实现根据业务负载自动伸缩。有关 Auto scaling 的内容请参考官方文档:

  4. https://docs.aws.amazon.com/autoscaling/plans/userguide/what-is-aws-auto-scaling.html。

  5. 然后根据官方文档创建 ECR 仓库:

  6. https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html。

  7. 假设该仓库的名字叫做 ecs-watchbot,则该 ECR 的 URI 为:123456789012.dkr.ecr.us-east-1.amazonaws.com/ecs-watchbot,这里的 123456789012 为用户的 AWS 账号。

  8. 从 github 下载 watchbot 代码:git clone https://github.com/mapbox/ecs-watchbot.git

  9. 进入 ecs-watchbot 子目录,创建 watchbot 容器镜像,注意下面命令中别忘了最后一个“.”。在本地构建 ecs-watchbot 容器镜像以后,上传到第一步中创建的 ECR 仓库里。编辑 Dockerfile,内容如下:

  10. Bash


   FROM ubuntu:16.04   # Setup
RUN apt-get update -qq && apt-get install -y curl
# Install node.js
RUN curl -s https://s3.amazonaws.com/mapbox/apps/install-node/v2.0.0/run | NV=4.4.2 NP=linux-x64 OD=/usr/local sh
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
RUN apt-get install -y nodejs
# Setup application directory
RUN mkdir -p /usr/local/src/watchbot
WORKDIR /usr/local/src/watchbot
# npm installation
COPY ./package.json ./
RUN npm install --production
# Copy files into the container
COPY ./index.js ./
COPY ./lib ./lib
COPY ./bin ./bin
# Logging onto the host EC2
VOLUME /mnt/log
# Run the watcher
CMD ["/bin/sh", "-c", "npm start"]
复制代码


然后构建容器镜像:
Bash
复制代码


   sudo docker build -t ecs-watchbot:v3.5.1.
复制代码


登录 ECR:
Bash
复制代码


   eval "sudo $(aws ecr get-login --region us-east-1 --no-include-email )"
复制代码


上传容器镜像到 ECR:
Bash
复制代码


   sudo docker tag ecs-watchbot:v3.5.1 123456789012.dkr.ecr.us-east-1.amazonaws.com/ecs-watchbot:v3.5.1
sudo docker push 123456789012.dkr.dkr.ecr.us-east-1.amazonaws.com/ecs-watchbot:v3.5.1
复制代码


  1. 在部署基于 watchbot 的 ECS 服务的时候,mapbox 在 github 上提供了一个样例 mapbox/ecs-telephone:https://github.com/mapbox/ecs-telephone。我们可以基于该样例进行修改,使其满足实际的需求。在安装该样例之前,先在当前主机上安装 js 以及其他组件:

  2. Bash


   sudo yum -y erase npmcurl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -sudo yum -y install nodejs
sudo npm install -g @mapbox/cfn-config
sudo npm install -g @mapbox/cloudfriend
sudo npm install -g @mapbox/watchbot
复制代码


  1. 该方案会使用 KMS 对 Amazon Cloudformation 的相关资源进行加密,比如环境变量等,因此需要先部署 KMS。从 github 下载 cloudformation-kms 的代码:

  2. git clone https://github.com/mapbox/cloudformation-kms.git

  3. 进入 cloudformation-kms 目录,执行下面的命令生成 Amazon Cloudformation 模板:

  4. Bash


   export NODE_PATH=/usr/lib/node_modules/@mapboxvalidate-template cloudformation-kms.template.jsbuild-template cloudformation-kms.template.js >> cloudformation-kms.template
复制代码


然后使用下面的命令创建 Amazon Cloudformation 堆栈:
Bash
复制代码


   aws cloudformation create-stack \
--stack-name kms-production \
--capabilities CAPABILITY_IAM \
--template-body file://cloudformation-kms.template \
--region us-east-1
复制代码


堆栈创建完毕以后,会有一个输出,其 export name 为 `cloudformation-kms-production`,这对应到生成的 KMS key 的 ARN,这个 ARN 会在 `ecs-telephone` 模板中被使用到。
复制代码


  1. 从 github 下载 ecs-telephone 代码:git clone https://github.com/mapbox/ecs-telephone.git进入 ecs-telephone 子目录,可以看到一个 Dockerfile 文件,使用该 Dockerfile 构建出的容器镜像里就包含了用户的业务逻辑。用户可以使用任何编程语言编写相应的业务逻辑。比如下面的例子使用 python 写了一段很简单的逻辑,该逻辑把传入当前容器的环境变量:message 的内容输出到 Amazon Cloudwatch log 里,保存该代码名为 domsg.py

  2. Bash


   import boto3
import os
message = os.environ["Message"]
print (message)
复制代码


然后编写一个 `Dockerfile`,如下所示:
Bash
复制代码


   FROM ubuntu:16.04
WORKDIR /usr/local/src/ecs-telephone
RUN apt-get update -qq
RUN apt-get install -y curl
RUN apt-get install -y python-pip python-dev build-essential
RUN pip install boto3
COPY domsg.py ./
CMD ["python","domsg.py"]
复制代码


运行下面的命令构建用户的任务容器镜像,tag 为123:
Bash
复制代码


   sudo docker build -t ecs-telephone:123 .
复制代码


创建 ECR 仓库,假设名为 `ecs-telephone`,对应的 URI 为 `012345678901.dkr.ecr.us-east-1.amazonaws.com/ecs- telephone`。然后把用户的任务容器镜像上传到 ECR 里:
Bash
复制代码


   eval "sudo $(aws ecr get-login --region us-east-1 --no-include-email )"
sudo docker tag ecs-telephone:123 012345678901.dkr.ecr.us-east-1.amazonaws.com/ecs-telephone:123
sudo docker push 012345678901.dkr.ecr.us-east-1.amazonaws.com/ecs-telephone:123
复制代码


  1. 进入 ecs-telephone/cloudformation 子目录,可以看到里面有一个 javascript 文件:ecs-telephone.template.js,可以利用该文件生成 Amazon Cloudformation 模板。打开该文件,其内容如下所示:

  2. Java


   const watchbot = require('@mapbox/watchbot');const cf = require('@mapbox/cloudfriend');const Parameters = {
GitSha: { Type: 'String' },
Cluster: { Type: 'String' },
Family: { Type: 'String' }
};
const watcher = watchbot.template({
cluster: cf.ref('Cluster'),
service: 'ecs-telephone',
family: cf.ref('Family'),
serviceVersion: cf.ref('GitSha'),
workers: 1,
reservation: { cpu: 256, memory: 128 },
env: { StackRegion: cf.region },
notificationEmail: 'devnull@mapbox.com'
});
复制代码


这里有三个输入参数:* `GitSha`:表示包含用户任务的 docker 镜像的 tag 值。* `Cluster`:表示整个任务平台所在的 Amazon ECS 集群的 ARN,注意这里需要输入 ARN 而不是集群的名称。该 ARN 可以使用 awscli 命令来获得:`aws ecs list-clusters`* `Family`:表示该批处理任务平台的名称,可以根据需要输入一个字符串,其内容没有特定要求。
还可以在这里根据实际需要修改相应的参数,包括:* `service`:表示使用该模板创建的 ECS 服务的名字。* `workers`:表示 watcher 在发现队列里有消息的时候,启动的包含用户的业务逻辑的容器。缺省为1个。* `reservation`:任务容器在运行时所需要的 CPU 和内存资源。* `notificationEmail`:各种通知产生以后,会发送到该邮箱里。
参数都修改完毕并保存以后,使用下面的命令创建 Amazon Cloudformation 模板:
Bash
复制代码


   export NODE_PATH=/usr/lib/node_modules
validate-template ecs-telephone.template.js
build-template ecs-telephone.template.js >> ecs-telephone.template
复制代码


打开该模板,找到包含 `Watchbot-worker-ecs-telephone` 字样的部分,可以看到如果使用该模板部署 ECS 服务,则会去找名为`ecs-telephone` 的 Amazon ECR 仓库,用户可以根据实际情况修改该 ECR 仓库名。
如果要在中国区运行该模板的话,需要手工进行修改。具体修改的地方包括:* 找到 EcrRegion 部分,在其中添加 `"cn-north-1": { "Region": "cn-north-1" }`* 搜索 amazonaws.com,除了 ecs-tasks.amazonaws.com 以外,其他都要添加 .cn,也就是改为 amazonaws.com.cn。* 找到下面这一段,将其删除。 [](https://s3.cn-north-1.amazonaws.com.cn/awschinablog/aws-ecs-parallel(6).png)](https://s3.cn-north-1.amazonaws.com.cn/awschinablog/aws-ecs-parallel(5).png)
复制代码


  1. 对该 Cloudformation 模板修改完毕以后,使用下面的命令运行模板从而创建 Amazon ECS 服务:

  2. Bash


   aws cloudformation create-stack \--stack-name ecs-telephone \--capabilities CAPABILITY_IAM \
--template-body file://ecs-telephone.template \
--parameters \
ParameterKey=GitSha,ParameterValue=123 \
ParameterKey=Cluster,ParameterValue=arn:aws:ecs:us-east-1:123456789012:cluster/production-cluster-ECSCluster\
ParameterKey=Family,ParameterValue=ecs-telephone \
--region us-east-1
复制代码


  1. 当 Amazon Cloudformation 堆栈部署完毕以后,进入 ECS 集群,可以看到创建了一个 ECS 服务,点击该服务,进入服务配置以后,有一个始终保持运行状态的 ECS 任务,该任务就是 watcher 容器。还可以通过控制台进入 Amazon SQS 界面,找到三个队列,其后缀名分别为 WatchbotDeadLetterQueueWatchbotTaskEventQueue 以及 WatchbotQueue。触发任务执行的消息需要发送到后缀为 WatchbotQueue 的队列,如果任务执行失败,则消息会放入后缀为 WatchbotDeadLetterQueue 的队列。在向 WatchbotQueue 发送消息的时候,必须遵循下面的格式:

  2. Bash


   {
"Subject": "Your subject",
"Message": "Your random message"
}
复制代码


该消息中的 Message 内容:“Your random message” 就会被上面第六步中的 `domsg.py` 输出到 Amazon CloudWatch 的 log group 里。我们可以进入 Amazon CloudWatch 控制台界面上,点击右边的 Logs,然后会看到包含 watchbot 的 log group,点击进去以后找到最新的 log stream 并点击进入,会看到该消息,说明整个流程正常运行起来了:  [](https://s3.cn-north-1.amazonaws.com.cn/awschinablog/aws-ecs-parallel(7).png)](https://s3.cn-north-1.amazonaws.com.cn/awschinablog/aws-ecs-parallel(7).png)
复制代码

结论

本文详细描述了如何基于 Amazon ECS 构建并行批处理任务平台。在该方案中,用户只需要关心业务逻辑的代码即可,其他启动,停止,重试任务容器以及自动扩展等操作都交由平台本身完成。另外,我们在部署任务容器时,任务处理的输出以及状态等信息应该保存到 Amazon S3 或者其他存储服务里(比如 RDS),确保任务容器在异常终止的时候,数据不会丢失。


作者介绍:


韩思捷


亚马逊 AWS 解决方案架构师,曾负责大企业客户在 AWS 上的售后技术支持工作,目前负责基于 AWS 的云计算方案架构咨询和设计。在加入 AWS 之前,在中国医药集团,Oracle 以及 EMC 研发中心工作,有多年开发和运维经验,并对各种数据库以及存储应用的高可用架构,方案及性能调优有深入研究。


本文转载自 AWS 技术博客。


原文链接:


https://amazonaws-china.com/cn/blogs/china/amazon-ecs-parallel-solution/


2019-10-22 08:00607

评论

发布
暂无评论
发现更多内容

3个月软件测试培训出来后的感悟-写给正在迷茫是否去学软件测试

伤心的辣条

Python 程序员 程序人生 软件测试 自动化测试

GetX — Flutter 开发的百宝箱

岛上码农

flutter ios 跨平台 安卓 6月月更

读《Software Systems Architecture》(04)—— Architectural Perspectives

术子米德

架构师成长笔记

读《Software Systems Architecture》(08)—— Concerns,Principles,and Decisions

术子米德

架构师成长笔记

flutter系列之:flutter中常用的Stack layout详解

程序那些事

flutter 程序那些事 6月月更

如何建立自己的看板系统

PingCode

29岁转行软件测试靠谱吗?一个过来人的心路历程送给迷茫的你

伤心的辣条

Python 程序员 程序人生 软件测试 自动化测试

读《Software Systems Architecture》(05)—— The Role of the Software Architect

术子米德

架构师成长笔记

读《Software Systems Architecture》(10)—— Identifying and Using Scenarios

术子米德

架构师成长笔记

详解MOVE PROTOCOL的测试版,让健康运动如影随形

BlockChain先知

leetcode 70. Climbing Stairs 爬楼梯(简单)

okokabcd

LeetCode 动态规划 数据结构与算法

在线文本字符串转十六进制工具

入门小站

工具

在线JSON转Excel工具

入门小站

工具

【LeetCode】 计算应缴税款总额 Java题解

Albert

LeetCode 6月月更

读《Software Systems Architecture》(06)—— Introduction to the Software Architecture Process

术子米德

架构师成长笔记

读《Software Systems Architecture》(07)—— The Architecture Definition Process

术子米德

架构师成长笔记

读《Software Systems Architecture》(09)—— Identifying and Engaging Stakeholders

术子米德

架构师成长笔记

盘点攻防演练中红队的主要工具(上)

穿过生命散发芬芳

工具 6月月更 攻防演练

为什么一定要参与开源项目?

源字节1号

开源 软件开发

读《Software Systems Architecture》(01)—— Introduction

术子米德

架构师成长笔记

linux之我常用的20条命令(之一)

入门小站

Linux

ConcurrentHashMap性能测试

FunTester

前端uni-app框架之实战主要技术栈day_3

恒山其若陋兮

6月月更

读《Software Systems Architecture》(02)—— Software Architecture Concepts

术子米德

架构师成长笔记

读《Software Systems Architecture》(03)—— Viewpoints and Views

术子米德

架构师成长笔记

浅谈微服务框架选型

阿泽🧸

微服务 6月月更

窃取证书的攻击流程及抓包分析

网络安全学海

黑客 网络安全 信息安全 渗透测试 WEB安全

Python自动化测试之模块、包与路径知识讲解

伤心的辣条

Python 程序员 程序人生 软件测试 自动化测试

从昇腾AI助力富士康产线升级,看中国智造的未来之路

脑极体

SOL staking质押现已在 AscendEX Earn 上线

鳄鱼视界

百里带你一文读懂selenium自动化测试(基于Python)

伤心的辣条

Python 程序人生 软件测试 自动化测试

基于 Amazon ECS 的并行批处理任务解决方案_语言 & 开发_亚马逊云科技 (Amazon Web Services)_InfoQ精选文章