1. 弹性伸缩到底解决什么问题,先别急着配置
做渠道商这些年,接触过大量中小企业客户,几乎每个人都在问同一个问题:流量高峰来了,服务器扛不住怎么办?
最典型的场景就是电商大促、营销活动上线、或者某个内容突然被推流。平时服务器利用率可能连20%都不到,活动一来瞬间飙到100%,用户访问卡顿、页面打不开、订单提交失败,运营那边急得跳脚,技术这边只能手动去云控制台一台台加机器。等机器终于起来了,流量高峰已经过去,加购的机器又闲置了,白白烧钱。这种“手动扩容慢半拍、流量过后成本收不住”的窘境,几乎每个中小企业都经历过。
阿里云弹性伸缩(Auto Scaling,ESS)就是专门解决这个问题的:它按照你设定的规则,自动增加或减少云服务器ECS实例的数量,流量涨了自动扩容,流量降了自动缩容,整个过程不需要人工介入。这篇文章我会从渠道商和运维实操的双重视角,把弹性伸缩的原理、配置步骤、参数计算、常见坑位一次性讲透,内容偏向可直接落地的方案,适合中小企业技术负责人、运维工程师,也适合正在帮客户做架构方案的渠道商伙伴参考。
先说清楚适用范围:如果你的业务是Web网站、API服务、小程序后端这类无状态应用,而且已经接了负载均衡SLB做流量分发,那弹性伸缩能发挥最大价值。如果业务还没做负载均衡,或者代码里把状态写在本地磁盘上,那需要先把架构调整好,再上弹性伸缩。
2. 核心概念与方案选型,弹性伸缩不是简单的“自动加机器”
2.1 一张图看懂弹性伸缩的工作机制
弹性伸缩的工作原理可以这样理解:你圈定一个伸缩组,相当于划了一块区域,在里面设定最小实例数、最大实例数、默认实例数这三道边界。再给这个伸缩组绑定一个伸缩配置,相当于定义“新机器长什么样”——用什么镜像、什么规格、什么安全组。然后你设定触发条件,比如CPU使用率超过70%持续5分钟就加一台机器,低于30%持续10分钟就减一台。
实际运行时会发现,整个系统就像装了一个智能恒温器:室温低了自动开暖气,室温高了自动开冷气,你只需要设定一个舒适区间,机器数量会自动维持在这个区间内。这背后的判断逻辑来自云监控的指标数据,弹性伸缩通过API读取指标,比对规则后执行扩容或缩容动作。
这里要特别强调一个概念:弹性伸缩管理的是“实例的数量”而不是“实例的规格”。它默认不会帮你把2核4G的机器变成4核8G,除非你用垂直伸缩功能(目前应用场景相对有限)。大多数业务的合理做法是横向扩容:增加机器数量,配合负载均衡分摊流量。
2.2 为什么说“备机方案”在中小企业里行不通
很多没接触过弹性伸缩的技术负责人,第一反应是“那我直接买几台备用机器放着,流量大了手动切过去不就行了”。这个思路不能说完全错,但放到真实环境里问题很多。
首先是成本问题。一台2核4G的ECS按量付费价格大概每小时0.2元到0.5元,10台备机一个月就算完全不用,也要烧掉上千块,一年下来就是上万。这还不算这些机器上需要同步代码、同步配置、跑监控代理的维护成本。其次是响应速度问题。手动扩容从收到告警、登录控制台、选配置、创建实例到服务真正起来,顺利的话8到10分钟,不顺利半小时都打不住。而大促流量不是匀速上涨的,经常是几分钟内就冲上来。等到你手动把机器加上去,用户早跑光了。
弹性伸缩的价值恰恰在这两个点上:需要的时候才创建实例,用完释放,不为闲置资源付费;通过API自动创建,加上预置好的镜像,实例从创建到对外提供服务可以压缩到3到5分钟。另外一个隐性价值是:手动操作容易出错,特别是在紧张的故障场景下,跨可用区选错、忘记挂负载均衡、安全组配置不对,这些错误在自动化流程里会被提前规避掉。
2.3 中小企业到底应该在什么阶段上弹性伸缩
我遇到过不少客户,业务每天就几百个请求,也非要上一套完整的弹性伸缩架构,结果组里永远只有一台机器,伸缩规则形同虚设。这不是弹性伸缩的问题,是使用时机不对。
比较合理的判断标准有两个:一是业务有明显的波峰波谷特征,比如白天用户多晚上少、工作日多周末少、月底月初有结账高峰等;二是现有固定资源已经没办法同时兼顾“高峰扛得住”和“低谷不浪费”。如果业务流量全年平稳,固定几台机器就够,那确实没必要上弹性伸缩,反而增加了架构复杂度。
还有一种情况特别适合用弹性伸缩:业务的“高峰”是不可预测的,比如营销活动、热点事件、被大V推荐。这类场景下你没法提前准备好固定资源,但又不能接受服务不可用,弹性伸缩几乎是唯一可行的自动化方案。我的建议是,判断要不要上弹性伸缩,先观察一两周云监控的CPU、带宽、QPS曲线,如果波峰波谷的落差超过3倍,就有上弹性伸缩的价值。
3. 一步步教你配置一套可用的伸缩组
3.1 前置条件:先打好三个基础
在动手创建伸缩组之前,有三个基础工作必须先完成,不然后面会遇到各种奇怪的问题。
第一,做好自定义镜像。弹性伸缩创建出来的新机器,本质上是“用你指定的镜像启动一台新ECS”。如果你用的是公共镜像系统,新机器起来后是裸系统,代码没部署、环境没配置、服务没启动。所以正确做法是:找一台已经部署好应用、配置好环境、验证过启动流程的机器,制作成自定义镜像。镜像包含操作系统、运行环境、代码包、自启动脚本,新实例一启动就能对外提供服务。这里有个细节:如果代码更新频繁,不要每次都重新制作镜像,常见做法是镜像里只放基础环境和启动脚本,代码通过对象存储或配置中心在启动时拉取最新版本。
第二,准备好负载均衡SLB。伸缩组里的多台机器必须有SLB来做流量分发,否则用户请求不知道该往哪台机器发。你需要提前创建一个SLB实例,配置好监听(80或443端口)、后端服务器组(可以先空着,伸缩组会自动把实例加入)、健康检查策略。健康检查路径最好是一个轻量的接口,不要是首页或者涉及数据库查询的接口,避免因为依赖组件抖动导致误判。
第三,确认业务无状态化。这是很硬性的一条:实例本地磁盘上不能存放必须长期保留的数据,比如用户上传的图片、本地数据库文件、日志文件。因为弹性伸缩会随时释放实例,本地数据会跟着消失。文件类数据要放到OSS,日志要打包投递到日志服务,数据库必须使用云数据库RDS。如果业务改造成无状态有困难,我的建议是先不碰弹性伸缩,优先解决这个问题。
3.2 创建伸缩组,最难理解的是那三个数字
进入ESS控制台,点击创建伸缩组,需要填一组参数,其中最难理解的通常是“最小实例数”“最大实例数”“默认实例数”这三个。
最小实例数:伸缩组无论如何都不会低于这个数量。它的作用是保证业务基础容量,比如你日常需要3台机器扛住常态流量,那最小实例数就设3。就算流量再低,系统也不会把实例缩到3以下。需要注意的是,最小实例数对应的实例费用是固定成本,设得太高就失去了弹性伸缩省钱的意义。
最大实例数:伸缩组最多能扩展到多少台。这个数字既是成本上限,也是安全护栏。万一报警规则配置失误或监控数据异常,也不会无限扩容把预算打爆。建议根据历史峰值流量乘以1.5到2的冗余系数来设定,同时要考虑下游数据库、缓存能承受多大的连接压力,不能只盯着应用层。举个例子,你的数据库连接数上限是500,每台应用实例占用50个连接,那应用实例最多10台,再多了数据库先扛不住。
默认实例数:伸缩组刚创建时的初始数量,也可以理解为日常兜底容量。一般与最小实例数保持一致,或者略高一点。如果业务有固定波峰,比如每天晚上8点的活跃高峰,可以把默认实例数设定为能扛住晚高峰峰值的数量,然后通过定时任务在高峰期前扩容、高峰后缩容。
这三个数字的设定没有绝对标准,本质上是成本、稳定性、响应速度三者的权衡。我见过比较稳的做法是:先按日常平均流量的1.5倍确定最小实例数,按历史最大流量的2倍确定最大实例数,默认实例数等于最小实例数。后续通过实际运行数据再逐步微调。
3.3 伸缩配置与启动模板,把“新机器长什么样”定义清楚
创建完伸缩组之后,需要创建一个伸缩配置,也可以使用ECS的启动模板。它定义了新增ECS实例的所有细节:地域可用区、实例规格、镜像、安全组、登录凭证、系统盘大小、标签等。
实例规格的选择有几个讲究。不要选择已经停售或即将停售的老规格,否则扩容时可能出现库存不足导致创建失败。同一伸缩组里可以配置多个实例规格,并设置优先级,弹性伸缩创建实例时会按优先级尝试,这样可以有效避开某一规格临时缺货的问题。实例规格的规格族尽量保持一致,避免同一组里出现不同代际的CPU,导致负载均衡算法下部分机器性能偏弱影响整体响应。
伸缩配置里最容易被忽略的是“密钥对”和“安全组”。如果直接使用密码登录,批量扩容出来的机器密码管理会非常混乱。建议统一使用密钥对,或者通过RAM角色授权实例访问OSS等云服务,而不是把AccessKey写死在业务配置里。安全组要与SLB的后端服务器放行规则匹配:SLB到后端实例的端口要放通,后端实例之间如果需要互相调用也要提前规划好安全组规则。
启动模板会比伸缩配置灵活一些,支持更多新特性。我个人的建议是:如果是新建环境,直接用启动模板;如果是从旧版伸缩配置迁移过来,可以先继续使用伸缩配置,后续逐步切换。
3.4 伸缩规则:手动、定时、动态告警怎么选
伸缩规则是弹性伸缩的“大脑”,决定了什么时候加机器、什么时候减机器。
手动伸缩规则最直观,就是你指定伸缩组内实例数变成多少,点击执行就立即生效。它的场景主要是应急操作,比如明确知道10分钟后有流量进来,手动把实例数拉上去。
定时任务适合流量高峰可以提前预判的场景。比如某客户的小程序每天晚上8点到10点是使用高峰,早上6点到8点也比较活跃,那就创建两个定时任务:一个在晚上7点30分执行扩容,把实例数调整为10;另一个在晚上10点30分执行缩容,把实例数调整为4。定时任务的核心在于时间点要提前设置好,留出实例初始化启动的时间。如果实例启动到对外提供服务需要5分钟,那扩容任务就要比流量高峰提前至少10分钟。
动态告警(指标触发)任务配置略微复杂,但它才是“弹性”二字的精髓。你需要指定监控指标(如CPU使用率)、阈值(如70%)、持续时间(如5分钟)、执行的动作(增加1台还是增加当前实例数的20%)。以CPU为例:平均CPU使用率连续5分钟超过70%,就扩容1台;连续10分钟低于30%,就缩容1台。这里的报警规则要避免过于灵敏,否则会出现“扩容完还没稳定又被缩掉”的抖动问题。
三种伸缩规则的定位不同:定时任务管可预期的峰谷,动态告警管不可预期的突发,手动规则管特殊情况的人工干预。合理的架构应该是定时任务兜底可预知流量,动态告警兜底突发流量,两条腿走路。
3.5 和SLB的联动配置,这一步千万别漏
伸缩组创建完成后,在伸缩组的“关联负载均衡”配置里,把提前准备好的SLB实例添加进去,伸缩组中的实例会自动注册到SLB的后端服务器组。这样用户流量经过SLB转发,按权重分发到组内的所有实例上。实例被缩容移除时,也会自动从SLB后端摘除,优雅地退出服务。
这里有两个经验值得分享。第一,如果业务同时对公网提供服务,不要把公网IP直接绑在伸缩组内的实例上,否则缩容时公网IP会被释放,DNS、白名单等一堆关联配置都要改。正确做法是SLB使用公网IP,后端ECS全部使用内网IP通信。第二,如果业务需要通过WebSocket或长连接和用户通信,要提前评估SLB对长连接的支持情况,以及缩容时长连接被断开对业务的影响,必要时开启连接优雅中断,给存量请求一点处理时间再断连。
4. 参数设置与容量规划,这些计算方法和经验值直接拿走用
4.1 最小实例数怎么算,先说一套基础逻辑
很多初次使用弹性伸缩的团队,会把最小实例数拍脑袋设为1或者2,看起来省成本,实际风险很大。最小实例数的计算应该以“系统能承受的最低服务水平”为基准。假设你的业务高峰期需要50台实例才能扛住,但低谷期1台就够,那最小实例数理论上确实是1。问题在于,如果流量在短时间内从低谷拉满,从1台扩展到50台需要的时间足够让用户体验到卡顿甚至不可用。
更务实的做法是考虑“保底水位”。观察业务近一周的流量曲线,找到除了极端低谷外,日常运行的最低流量点,反推出需要多少台实例能支撑这个流量,然后乘以1.2的安全系数,作为最小实例数。比如某业务日常最低流量需要4台实例支撑,那最小实例数就设5。这样即使突发扩容来不及,系统也有5台实例撑着,不会直接被打垮。
另外要注意:如果伸缩组使用均衡分布策略,同时选了多个可用区,最小实例数最好能被可用区数量整除。比如有2个可用区,最小实例数设4或6比较合理,让实例均匀分布,避免出现单可用区故障时只剩一侧可用的情况。
4.2 实例规格与容量估算,一个案例讲清楚
容量规划这块,我总结了一个比较实用的流程:先做压测,得出单台实例能支撑多少QPS或多少并发连接,再根据业务预估的峰值流量反推需要的实例数。
举个例子。某电商客户做了压测后发现:一台4核8G的ECS实例,在响应时间低于500毫秒的要求下,最多能支撑2000QPS。大促预估峰值流量是20000QPS,那就需要10台实例承载。加上30%的冗余缓冲,实际需要13台。最大实例数可以设置在15到20之间,因为大促峰值往往出现在活动开始和整点秒杀时间段,瞬时流量可能是均值的几倍。
这个案例里有一个容易踩的坑:压测一定要模拟真实业务场景,不能只压一个静态页面。我曾经见过客户拿一个空接口压测,测出来的QPS非常高,结果上线后真实业务一跑,数据库连接、日志写入、外部API调用全部拖慢速度,单机QPS直接腰斩。建议在压测脚本里加入数据库读写、缓存访问、文件上传下载这些真实逻辑,压出来的数据才有参考价值。
4.3 冷却时间、预警阈值、伸缩步长怎么搭配
冷却时间(Cooldown)是弹性伸缩里特别重要但总被忽略的参数。它指的是,在一个伸缩动作完成后,进入一段冷却时间,期间不会触发新的伸缩动作。默认值是300秒,也就是5分钟。这个设计的目的是防止系统频繁抖动:扩容刚加了机器,CPU还没降下来又触发一次扩容,机器越加越多,等流量真的退了又连环触发缩容。
中小企业的典型配置建议是:冷却时间300秒或以上,告警持续时间3到5分钟(不要设1分钟,太容易误触发)。伸缩步长上,扩容一次加1台或一个固定数量,缩容一次减1台。这个“每次只变1台”的策略看起来很慢,实际上在冷却时间配合下,10分钟就能完成5台机器的变化,足够应对大多数场景。
如果业务流量波动特别大,比如游戏开服或直播大促,可以考虑使用“目标追踪规则”,后台会自动计算需要增加多少台实例才能把指标拉回目标值,比固定步长更智能。举个例子,目标追踪规则设定CPU目标值60%,当CPU到70%时,它会估算当前10台实例不够,可能需要12台,就一次扩展2台,收敛速度更快。不过目标追踪规则的调优需要一定观察周期,我建议先在测试环境跑几天,看扩缩容曲线是否符合预期再上生产。
4.4 扩容出来的机器需要多快就绪,这块花费的功夫最大
弹性伸缩把机器创建出来只是第一步,服务真正可用才是最终目标。这里涉及到“实例启动时间”的概念,包括:系统启动、云助手执行初始化脚本、部署组件启动、应用健康检查通过,这个过程从几十秒到几分钟不等。
为了压缩这个时间,我推荐做三件事。第一,镜像越精简越好,把不常用的软件包和缓存清理干净,减少系统启动时的加载项。第二,利用实例的“自定义数据(User Data)”功能,在机器启动时自动执行一段脚本,完成挂载数据盘、调整内核参数、拉取最新代码、启动应用这些操作。第三,用云助手而不是手工维护脚本,方便批量下发命令到所有实例。实测下来,优化后的实例从创建到健康检查通过,可以稳定控制在3分钟内。
蚂蚁搬家式的优化还有一处:健康检查。SLB的健康检查频率默认是2秒一次,超时时间2秒,如果检查频率太密集,后端实例刚启动还在初始化就可能被误判为不健康。建议把健康检查的“健康阈值”设为3次,“不健康阈值”设为3次,给实例留出足够的预热时间。这个细节可以让扩容实例的“可用率”明显提升。
5. 常见问题与排障实录,这些坑都是一台台填出来的
5.1 流量高峰来了,弹性伸缩为什么没扩容
这是客户问得最多的问题,没有之一。排查思路按照下面五步走,基本能定位问题:
- 检查监控数据是否正常。打开云监控控制台,查看伸缩组内实例的CPU指标是否有数据。如果监控数据缺失,告警规则永远不会触发。常见原因是云监控插件没有安装成功,或者版本太老,需要重新安装。
- 检查告警规则与伸缩规则是否“对齐”。告警规则报警后,必须绑定对应的伸缩规则才能触发扩容。很多人创建了告警规则,但忘记在“报警任务”里关联伸缩规则,结果空有告警邮件,伸缩组纹丝不动。
- 检查冷却时间。刚发生完一次伸缩动作,冷却时间内再次触发会不生效。如果确实需要立即再扩容,可以在控制台“手动执行伸缩规则”,强制加机器。
- 检查最大实例数是否到了上限。如果实例数已经等于最大实例数,即使触发规则也不会再创建新实例。把这个数字调大,或者检查业务是否真的还需要继续扩容。
- 检查时间窗口。告警触发后,实例创建需要时间,不要在一两分钟内就认定“没扩容”,从容发出去到机器就绪,3到5分钟是正常节奏。
排障实录里有个让我印象深刻的案例:某客户大促当天发现扩不出来,排查了半天最后发现是伸缩组选了4个可用区,其中一个可用区的指定实例规格库存不足,创建请求卡在那里反复重试。后面把伸缩配置改成多规格优先级,问题立即解决。
5.2 扩容出来的实例一直不健康,SLB就是不给它转发流量
新扩容的实例出现在SLB后端,但健康检查一直显示异常,这是第二高发的问题。主要原因有三类,排查时按这个顺序查:
第一,业务端口没起来。新实例的安全组、服务端口要和健康检查路径匹配。检查一下应用进程是否真的在运行,端口是否在监听。如果没有,多半是镜像里的自启动服务配置有问题,或者User Data执行报错。上云服务器控制台看该实例的“自定义数据执行日志”,能直接看到脚本报错信息。
第二,健康检查路径返回了非预期状态码。SLB健康检查默认判断的是HTTP状态码,如果后端接口返回了302跳转、401认证、或者5xx错误,都会被判定为不健康。很多人的应用框架默认对未登录用户返回302,健康检查就一直失败。建议专门开发一个轻量级的健康检查接口,返回200和固定的JSON内容,不要经过中间件鉴权。
第三,后端实例和SLB之间的网络不通。检查安全组是否放行了SLB所在网段到后端实例的端口,特别是跨VPC或使用不同安全组的时候,最容易被安全组规则挡住。在SLB控制台可以直接测试健康检查,返回的信息能帮助判断是连接超时还是响应异常。
5.3 实例被缩容,却把正在处理的请求中断了
弹性伸缩的缩容逻辑是把实例移出伸缩组并释放,但如果你不管业务请求,只管机械地执行缩容,就会出现正在处理的请求被一刀切掉的情况,用户端看到的是“请求失败”。
解决办法分两层。第一层是“摘除与等待”机制:在缩容前,先把实例从SLB后端移除,此时新请求不会再转发过来,但已经建立的连接仍然可以继续处理存量请求。等存量请求处理完再释放实例。这个功能在弹性伸缩的“缩容冷却”和SLB的连接优雅中断里可以配置,核心思路就是让实例“软退出”而不是“硬下线”。
第二层是保护关键实例。在伸缩组里可以对某台实例开启“实例保护”,开启后缩容规则不会移除它。这个功能适合那些承担特殊任务的实例,比如运行着临时数据处理任务的机器。不过要注意,被保护的实例如果积攒太多,会让最小实例数形同虚设,定期巡检累积下来的“僵尸保护实例”是很多团队成本超支的隐形原因。
5.4 频繁扩缩容,一天几十次,成本不降反升
有客户跑了一周后反馈:弹性伸缩确实自动扩缩容了,但是频率非常高,一天能折腾二三十次,费用和手动管理差不多了。这是典型的“伸缩抖动”问题,本质是规则设置得太敏感。
抖动的根源是:告警规则持续时间设置得太短,加上冷却时间太小,导致系统对监控指标的瞬时波动反应过度。比如CPU冲到70%持续2分钟就扩容,扩容后机器还在初始化,CPU指标没降下来,又触发了一次扩容。等机器都起来了,流量退潮,CPU快速下降触发缩容,反复横跳。
治理方案一般从三个参数入手:把告警持续时长从2分钟拉长到5分钟;把冷却时间从300秒调整到600秒;缩小伸缩步长,由一次加2台改为一次加1台。如果是目标追踪规则,适当降低目标值,让系统有更多缓冲空间。经过这样一轮调整,绝大多数抖动问题都能解决。我在实践中还会建议客户把“缩容”的触发条件设置得比“扩容”更保守一些,比如扩容是CPU持续5分钟超过70%,缩容是CPU持续15分钟低于30%。让缩容慢半拍,避免流量刚回落就被“追尾”缩容。
5.5 突发流量来临,扩容还在路上,系统已经被打穿
这是弹性伸缩的“先天局限”:从检测到指标异常到新实例真正开始服务,最短也要3到5分钟。如果是秒杀、大V转发这种瞬间流量,前面的请求很可能直接打到现有的少量实例上,还没等到扩容就超时了。
应对思路是预判,而不是依赖事后扩容。综合几个手段:定时任务提前扩容是最简单有效的,对于大促和活动,宁可提前半小时把机器加上去,也不要赌瞬间流量不会打爆系统;启用“峰值预测”功能,ESS会根据历史流量曲线预测未来几小时的需求,自动提前扩容;应用层做限流降级,通过Sentinel或网关限流,把超出的请求直接拒绝,保护后端实例不被压垮;数据库和缓存提前升配或者扩容连接数,避免应用扛住了,数据库先挂了。
我在帮客户做大促保障时,习惯把扩容的“冗余水位”定得比较保守——即使预测需要10台,我也建议提前备到15台左右。多出来的几台机器在大促结束后可以缩掉,费用可控,但少几台的代价可能是整个活动事故。
6. 最后分享一点实操体会
弹个伸缩配置本身并不难,难的是对业务的理解和参数的持续调优。我从渠道商视角给三条很实用的建议:
第一,上生产前一定要在测试环境完整演练。至少跑一周,观察扩缩容记录,确认没有异常抖动,再切生产。第二,把弹性伸缩看作一个长期迭代的系统,上线后每周看一次扩缩容报告,结合业务流量变化持续调整参数,而不是配完就不管了。第三,如果有预算,把重要业务配上告警通知,扩容缩容发生时相关人员能第一时间感知,很多问题在初期就能被人工介入解决。
再分享一个小技巧:弹性伸缩组里的实例,建议统一打上伸缩组标签,这样一来费用账单里能一眼看清这些实例花了多少钱,比月底对账时一行行找实例名省心得多。我这里遇到的客户,凡是坚持这样做的,在下一次做容量规划时都有清晰的数据支撑。