40、动态 EC2 实例池的解耦与自动伸缩

动态 EC2 实例池的解耦与自动伸缩

在云计算环境中,根据需求动态调整虚拟机数量是实现资源高效利用和应用性能优化的关键。本文将介绍如何通过解耦动态 EC2 实例池来实现自动伸缩,以满足不同工作负载的需求。

1. 解耦动态 EC2 实例池的概念

当需要根据需求扩展运行博客平台的虚拟机数量时,自动伸缩组可以帮助提供适量的统一虚拟机,而伸缩计划或 CloudWatch 警报可以自动增加或减少所需的 EC2 实例数量。但用户如何访问实例池中的 EC2 实例以浏览托管的文章呢?HTTP 请求应路由到哪里?

解耦是解决这些问题的关键。解耦分为同步解耦和异步解耦:
- 同步解耦 :使用弹性负载均衡器(ELB),它作为入口点,将请求分发到一组虚拟机中。
- 异步解耦 :使用消息队列(SQS),生产者发送的消息存储在队列中,虚拟机异步轮询队列并处理消息。

解耦和可扩展的应用程序需要无状态服务器,无状态服务器将共享数据远程存储在数据库或存储系统中。以下是两个实现无状态服务器概念的示例:
- WordPress 博客 :通过 ELB 解耦,基于 CPU 利用率使用自动伸缩和 CloudWatch 进行扩展,数据外包给 MySQL 数据库(RDS)和网络文件系统(EFS)。
- URL2PNG 截图应用 :通过队列(SQS)解耦,基于队列长度使用自动伸缩和 CloudWatch 进行扩展,数据外包给 NoSQL 数据库(DynamoDB)和对象存储(S3)。

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(Request):::process --> B(Load balancer):::process
    B --> C(Auto-scaling):::process
    C --> D(Virtual machines 1..n):::process
    E(Message producers):::process --> F(SQS message queue):::process
    F --> G(Virtual machines 1..n):::process
2. 通过负载均衡器同步解耦动态 EC2 实例池

处理 HTTP(S) 请求是一个同步任务。当使用动态 EC2 实例池运行 Web 应用程序时,通常使用负载均衡器将 EC2 实例与用户请求解耦。负载均衡器将 HTTP(S) 请求转发到多个 EC2 实例,作为动态 EC2 实例池的单一入口点。

假设公司有一个企业博客,用于发布公告和与社区互动。营销部门抱怨晚上流量达到高峰时页面速度慢甚至超时。可以利用 AWS 的弹性,根据当前工作负载扩展 EC2 实例的数量。

公司使用流行的博客平台 WordPress 作为企业博客。以下是实现高可用伸缩架构的服务:
- EC2 实例 :运行 Apache 以提供 WordPress(PHP 应用程序)。
- RDS :提供通过多可用区部署实现高可用性的 MySQL 数据库。
- EFS :存储 PHP、HTML 和 CSS 文件以及用户上传的图像和视频。
- ELB :将 Web 服务器与访问者同步解耦。
- 自动伸缩和 CloudWatch :根据所有运行虚拟机的当前 CPU 负载扩展 EC2 实例的数量。

2.1 创建可扩展的 WordPress 环境

可以通过以下步骤创建可扩展的 WordPress 环境:
1. 执行以下命令创建 CloudFormation 堆栈,替换 $Password 为自己的 8 到 30 位字母和数字组成的密码:

$ aws cloudformation create-stack --stack-name wordpress \
  --template-url https://s3.amazonaws.com/awsinaction-code2/chapter17/wordpress.yaml \
  --parameters ParameterKey=WordpressAdminPassword,ParameterValue=$Password \
  --capabilities CAPABILITY_IAM
  1. 等待最多 15 分钟,堆栈创建完成。登录 AWS 管理控制台,导航到 AWS CloudFormation 服务,监控名为 wordpress 的 CloudFormation 堆栈的创建过程。

以下是 CloudFormation 模板的重要部分:

LaunchConfiguration:
  Type: 'AWS::AutoScaling::LaunchConfiguration'
  Metadata: # [...]
  Properties:
    AssociatePublicIpAddress: true
    ImageId: 'ami-6057e21a'
    InstanceMonitoring: false
    InstanceType: 't2.micro'
    SecurityGroups:
      - !Ref WebServerSecurityGroup
    KeyName: !Ref KeyName
    UserData: # [...]

AutoScalingGroup:
  Type: 'AWS::AutoScaling::AutoScalingGroup'
  DependsOn:
    - EFSMountTargetA
    - EFSMountTargetB
  Properties:
    TargetGroupARNs:
      - !Ref LoadBalancerTargetGroup
    LaunchConfigurationName: !Ref LaunchConfiguration
    MinSize: 2
    MaxSize: 4
    DesiredCapacity: 2
    HealthCheckGracePeriod: 300
    HealthCheckType: ELB
    VPCZoneIdentifier:
      - !Ref SubnetA
      - !Ref SubnetB
    Tags:
      - PropagateAtLaunch: true
        Value: wordpress
        Key: Name
    # [...]
2.2 创建新博客文章

CloudFormation 堆栈创建完成后,按以下步骤创建包含图像的新博客文章:
1. 选择 wordpress CloudFormation 堆栈,切换到“Outputs”选项卡。
2. 使用现代 Web 浏览器打开“URL”键显示的链接。
3. 在导航栏中搜索“Log In”链接并点击。
4. 使用用户名 admin 和创建堆栈时指定的密码登录。
5. 点击左侧菜单中的“Posts”。
6. 点击“Add New”。
7. 输入标题和文本,并上传图像到文章。
8. 点击“Publish”。
9. 点击“View Post”链接返回博客。

2.3 负载测试

准备了一个负载测试,将在几分钟内发送 500,000 个请求到 WordPress 环境。使用 Apache Bench 工具进行负载测试,执行以下命令,替换 $UrlLoadBalancer 为负载均衡器的 URL:

$ ab -n 500000 -c 15 -t 300 -s 120 -r $UrlLoadBalancer

更新 CloudFormation 堆栈以启动负载测试:

$ aws cloudformation update-stack --stack-name wordpress \
  --template-url https://s3.amazonaws.com/awsinaction-code2/chapter17/wordpress-loadtest.yaml \
  --parameters ParameterKey=WordpressAdminPassword,UsePreviousValue=true \
  --capabilities CAPABILITY_IAM

使用 AWS 管理控制台观察以下情况:
1. 打开 CloudWatch 服务,点击左侧的“Alarms”。
2. 负载测试开始约 3 分钟后,名为 TargetTracking-wordpress-AutoScalingGroup-*-AlarmHigh-* 的警报将进入“ALARM”状态。
3. 打开 EC2 服务,列出所有 EC2 实例,观察两个额外的实例启动。最终将看到总共五个实例(四个 Web 服务器和运行负载测试的 EC2 实例)。
4. 返回 CloudWatch 服务,等待名为 TargetTracking-wordpress-AutoScalingGroup-*-AlarmLow-* 的警报进入“ALARM”状态。
5. 打开 EC2 服务,列出所有 EC2 实例,观察两个额外的实例消失。最终将看到总共三个实例(两个 Web 服务器和运行负载测试的 EC2 实例)。

整个过程大约需要 20 分钟。通过自动伸缩,WordPress 环境现在可以适应当前工作负载,解决了晚上页面加载缓慢甚至超时的问题。

3. 通过队列异步解耦动态 EC2 实例池

假设正在开发一个社交书签服务,用户可以保存和共享链接。提供链接网站的预览是一个重要功能,但从 URL 转换为 PNG 的过程在晚上用户添加新书签时会导致高负载,从而导致用户对应用程序的响应时间不满。

通过异步解耦动态 EC2 实例池,可以将负载密集型工作负载隔离到后台作业中,保证任何时候都有较低的响应时间。当基于工作负载进行扩展时,异步解耦提供了一个优势,因为请求不需要立即响应,可以将请求放入队列中,并根据队列长度扩展 EC2 实例的数量。

3.1 URL2PNG 应用架构

为了处理晚上的高峰负载,使用自动伸缩并解耦新书签的创建和网站预览的生成过程。架构包括用于异步解耦的 SQS 队列和用于存储生成图像的 S3。创建书签将触发以下过程:
1. 消息发送到 SQS 队列,包含 URL 和新书签的唯一 ID。
2. 运行 Node.js 应用程序的 EC2 实例轮询 SQS 队列。
3. Node.js 应用程序加载 URL 并创建截图。
4. 截图上传到 S3 存储桶,对象键设置为唯一 ID。
5. 用户可以使用唯一 ID 直接从 S3 下载截图。

使用 CloudWatch 警报监控 SQS 队列的长度。如果队列长度达到 5,启动一个额外的虚拟机来处理工作负载。当队列长度低于 5 时,另一个 CloudWatch 警报减少自动伸缩组的期望容量。

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(Message producers):::process --> B(SQS message queue):::process
    B --> C(CloudWatch metric and alarm):::process
    C --> D(Auto-scaling):::process
    D --> E(Virtual machines):::process
    E --> F(Convert the URL to an image (PNG)):::process
    F --> G(S3 object store media files):::process
    E --> B(Queue):::process
3.2 创建 URL2PNG 应用

执行以下命令创建 CloudFormation 堆栈,替换 $ApplicationID 为应用程序的唯一 ID:

$ aws cloudformation create-stack --stack-name url2png \
  --template-url https://s3.amazonaws.com/awsinaction-code2/chapter17/url2png.yaml \
  --parameters ParameterKey=ApplicationID,ParameterValue=$ApplicationID \
  --capabilities CAPABILITY_IAM

等待最多 5 分钟,堆栈创建完成。登录 AWS 管理控制台,导航到 AWS CloudFormation 服务,监控名为 url2png 的 CloudFormation 堆栈的创建过程。

由于队列中的消息数量与处理消息的 EC2 实例数量不相关,因此使用步骤伸缩策略。以下是相关的 CloudFormation 模板部分:

HighQueueAlarm:
  Type: 'AWS::CloudWatch::Alarm'
  Properties:
    EvaluationPeriods: 1
    Statistic: Sum
    Threshold: 5
    AlarmDescription: 'Alarm if queue length is higher than 5.'
    Period: 300
    AlarmActions:
      - !Ref ScalingUpPolicy
    Namespace: 'AWS/SQS'
    Dimensions:
      - Name: QueueName
        Value: !Sub '${SQSQueue.QueueName}'
    ComparisonOperator: GreaterThanThreshold
    MetricName: ApproximateNumberOfMessagesVisible

ScalingUpPolicy:
  Type: 'AWS::AutoScaling::ScalingPolicy'
  Properties:
    AdjustmentType: 'ChangeInCapacity'
    AutoScalingGroupName: !Ref AutoScalingGroup
    PolicyType: 'StepScaling'
    MetricAggregationType: 'Average'
    EstimatedInstanceWarmup: 60
    StepAdjustments:
      - MetricIntervalLowerBound: 0
        ScalingAdjustment: 1
3.3 负载测试

准备了一个负载测试,将快速为 URL2PNG 应用程序生成 250 条消息。执行以下命令更新 CloudFormation 堆栈以启动负载测试:

$ aws cloudformation update-stack --stack-name url2png \
  --template-url https://s3.amazonaws.com/awsinaction-code2/chapter17/url2png-loadtest.yaml \
  --parameters ParameterKey=ApplicationID,UsePreviousValue=true \
  --capabilities CAPABILITY_IAM

使用 AWS 管理控制台观察以下情况:
1. 打开 CloudWatch 服务,点击左侧的“Alarms”。
2. 负载测试开始几分钟后,名为 url2png-HighQueueAlarm-* 的警报将进入“ALARM”状态。
3. 打开 EC2 服务,列出所有 EC2 实例,观察一个额外的实例启动。最终将看到总共三个实例(两个工作者和运行负载测试的 EC2 实例)。
4. 返回 CloudWatch 服务,等待名为 url2png-LowQueueAlarm-* 的警报进入“ALARM”状态。
5. 打开 EC2 服务,列出所有 EC2 实例,观察额外的实例消失。最终将看到总共两个实例(一个工作者和运行负载测试的 EC2 实例)。

整个过程大约需要 15 分钟。通过自动伸缩,URL2PNG 应用程序现在可以适应当前工作负载,解决了截图生成缓慢的问题。

4. 总结
  • 可以使用自动伸缩通过启动配置和自动伸缩组来启动多个相同的虚拟机。
  • EC2、SQS 等服务向 CloudWatch 发布指标(如 CPU 利用率、队列长度等)。
  • CloudWatch 警报可以更改自动伸缩组的期望容量,从而根据 CPU 利用率或其他指标增加虚拟机数量。
  • 如果要根据当前工作负载扩展虚拟机,虚拟机需要是无状态的。
  • 为了在多个虚拟机之间分配负载,需要使用负载均衡器进行同步解耦或使用消息队列进行异步解耦。

通过动态解耦和自动伸缩,可以根据工作负载动态调整资源,实现高效的云计算环境。

5. 清理资源

执行以下命令删除与 WordPress 环境对应的所有资源:

$ aws cloudformation delete-stack --stack-name wordpress

执行以下命令删除与 URL2PNG 环境对应的所有资源,替换 $ApplicationID

$ aws s3 rm s3://$ApplicationID --recursive
$ aws cloudformation delete-stack --stack-name url2png

动态 EC2 实例池的解耦与自动伸缩

6. 自动伸缩与解耦的优势总结

自动伸缩和实例池解耦在云计算环境中具有显著优势,以下通过表格形式进行总结:
| 优势 | 同步解耦(负载均衡器) | 异步解耦(消息队列) |
| — | — | — |
| 负载分配 | 均匀分发 HTTP(S) 请求,确保各实例负载均衡,提高响应速度 | 隔离负载密集型任务,将请求存储在队列,避免请求丢失,保证低响应时间 |
| 资源利用 | 根据 CPU 等指标自动调整实例数量,避免资源浪费或不足 | 依据队列长度精准扩展实例,资源利用更高效 |
| 应用适应性 | 适用于需即时响应的 Web 应用,如 WordPress 博客 | 适合处理可延迟任务,如 URL2PNG 截图生成 |
| 系统稳定性 | 提供单一入口点,增强系统可用性和稳定性 | 防止请求积压,维持系统稳定运行 |

7. 不同解耦方式的适用场景分析

不同的解耦方式适用于不同的应用场景,以下是详细分析:
- 同步解耦(负载均衡器)
- Web 应用 :如企业博客、电商网站等,用户请求需即时响应,负载均衡器可将请求快速分发到多个 EC2 实例,保证页面快速加载。
- 实时交互系统 :如在线聊天、视频会议等,对响应时间要求极高,同步解耦能确保用户体验。
- 异步解耦(消息队列)
- 批量处理任务 :如数据备份、文件转换等,可将任务放入队列,后台实例按顺序处理,不影响前端响应。
- 高并发场景 :如秒杀活动、节日促销等,请求量瞬间剧增,消息队列可缓冲请求,避免系统崩溃。

8. 动态伸缩的注意事项

在进行动态伸缩时,需要注意以下几点:
- 指标选择 :选择合适的 CloudWatch 指标进行伸缩,如 CPU 利用率、请求数量、队列长度等。确保指标能准确反映系统负载,避免误判。
- 伸缩策略 :根据应用特点选择合适的伸缩策略,如目标跟踪策略、步骤伸缩策略等。合理设置伸缩阈值和调整幅度,避免过度伸缩。
- 实例预热 :新实例启动后,可能需要一段时间才能达到稳定状态。设置实例预热时间,避免因新实例未就绪而影响系统性能。
- 资源清理 :伸缩过程中,及时清理不再使用的资源,避免资源浪费和成本增加。

9. 案例对比分析

为了更直观地了解同步解耦和异步解耦的差异,以下通过 WordPress 博客和 URL2PNG 应用的案例进行对比:
| 对比项 | WordPress 博客(同步解耦) | URL2PNG 应用(异步解耦) |
| — | — | — |
| 解耦方式 | 负载均衡器(ELB) | 消息队列(SQS) |
| 伸缩依据 | CPU 利用率 | 队列长度 |
| 数据存储 | RDS(MySQL 数据库)、EFS(网络文件系统) | S3(对象存储)、DynamoDB(NoSQL 数据库) |
| 应用场景 | 实时响应的 Web 博客 | 负载密集型的截图生成 |
| 伸缩效果 | 解决页面加载慢和超时问题 | 解决截图生成缓慢问题 |

10. 未来趋势展望

随着云计算技术的不断发展,动态 EC2 实例池的解耦与自动伸缩将朝着更加智能化、自动化的方向发展:
- 智能伸缩 :利用机器学习和人工智能技术,自动分析系统负载和性能数据,预测未来负载趋势,实现更精准的伸缩。
- 混合解耦 :结合同步解耦和异步解耦的优势,根据不同的业务需求和工作负载,灵活选择解耦方式,提高系统的适应性和性能。
- 跨云伸缩 :支持在多个云平台之间进行伸缩,实现资源的优化配置和成本的降低。

11. 总结

通过本文的介绍,我们了解了动态 EC2 实例池的解耦与自动伸缩的重要性和实现方法。同步解耦和异步解耦为不同类型的应用提供了有效的负载分配和资源扩展方案,CloudWatch 警报和自动伸缩组则确保了系统能够根据工作负载动态调整资源。

在实际应用中,需要根据应用的特点和需求选择合适的解耦方式和伸缩策略,同时注意指标选择、实例预热和资源清理等问题。通过合理运用这些技术,可以实现高效的云计算环境,提高系统的性能和可靠性。

最后,不要忘记在使用完相关资源后,按照以下命令清理资源:

# 删除 WordPress 环境资源
$ aws cloudformation delete-stack --stack-name wordpress

# 删除 URL2PNG 环境资源,替换 $ApplicationID
$ aws s3 rm s3://$ApplicationID --recursive
$ aws cloudformation delete-stack --stack-name url2png

希望本文能为你在云计算环境中实现动态伸缩提供有益的参考和指导。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值