【免费下载链接】floci
Light, fluffy, and always free - The AWS Local Emulator alternative
Floci 以内存态存储实现 EC2 Auto Scaling(autoscaling)Query API 的 45 个操作,覆盖启动配置、自动扩缩组、生命周期钩子、扩缩策略、计划任务与 Warm Pool 的完整状态管理,并配备一个每 10 秒运行一次的容量协调器(Reconciler),通过调用 EC2RunInstances/TerminateInstances真正拉起或销毁实例来维持 DesiredCapacity。本文结合 docs/services/autoscaling.md 与 AutoScalingService.java 等源码,逐层拆解其协议形态、操作清单、协调器原理与边界行为,帮助你在本地开发与测试中正确使用 Floci 的 Auto Scaling 能力。
协议与 ARN 形态
Floci 的 Auto Scaling 服务使用 AWS 经典Query 协议:客户端以POST /发起请求,Action表单参数指定具体操作,凭证作用域(credential scope)为autoscaling,服务端以 XML 响应返回结果。从源码看,请求分发由 AutoScalingQueryHandler.java 中的switch (action)完成,支持 45 个动作,未知动作返回UnsupportedOperation错误。
三类核心资源使用以下 ARN 格式:
- 自动扩缩组:
arn:aws:autoscaling:<region>:<account>:autoScalingGroup:<uuid>:autoScalingGroupName/<name> - 启动配置:
arn:aws:autoscaling:<region>:<account>:launchConfiguration:<uuid>:launchConfigurationName/<name> - 扩缩策略:
arn:aws:autoscaling:<region>:<account>:scalingPolicy:<uuid>:autoScalingGroupName/<group>/policyName/<name>
源码中 ARN 通过AwsArnUtils.Arn.of("autoscaling", region, accountId, ...)生成(见 AutoScalingService.java),<uuid>部分实际由资源类型与名称构成,区域与账号 ID 取自请求上下文。
存储模型:以区域为命名空间的内存态存储
Floci 的 Auto Scaling 状态全部保存在AutoScalingService持有的内存 Map 中,键统一为region::name(组、启动配置)或region::group::name(钩子、策略、计划任务)等组合。服务启动时通过StorageBackedMap将以下 8 类数据持久化到 JSON 文件(见 AutoScalingService.java):
| 存储文件 | 内容 |
|---|---|
autoscaling-launch-configurations.json | 启动配置 |
autoscaling-groups.json | 自动扩缩组(含实例列表) |
autoscaling-lifecycle-hooks.json | 生命周期钩子 |
autoscaling-policies.json | 扩缩策略 |
autoscaling-activities.json | 扩缩活动日志 |
autoscaling-instance-refreshes.json | 实例刷新记录 |
autoscaling-scheduled-actions.json | 计划任务 |
autoscaling-warm-pools.json | Warm Pool 配置 |
由于键包含区域,同一名称在不同区域下互不干扰;describe类操作也会按区域过滤。这保证了对多区域、多账号模拟的一致行为。
操作全景:45 个 API 的兼容矩阵
启动配置(Launch Configurations)
| 操作 | 说明 |
|---|---|
CreateLaunchConfiguration | 存储模板:ImageId、InstanceType、KeyName、SecurityGroups、UserData、IamInstanceProfile、InstanceMonitoring、BlockDeviceMappings |
DescribeLaunchConfigurations | 按名称列表过滤;无过滤时返回全部 |
DeleteLaunchConfiguration | 删除指定启动配置,不存在时抛ValidationError |
源码中的校验逻辑与 AWS 保持一致:请求要么携带InstanceId,要么同时携带ImageId与InstanceType,否则抛ValidationError(错误消息见 AutoScalingService.java)。若传入InstanceId,Floci 会查询对应 EC2 实例并自动补全缺失的ImageId、InstanceType、KeyName、SecurityGroups、UserData、IamInstanceProfile,模拟 AWS 的"从实例创建启动配置"行为。InstanceMonitoring默认视为启用(TRUE),而AssociatePublicIpAddress的缺席是有意义的(显式false优先于子网默认值),两者语义不同。
自动扩缩组(Auto Scaling Groups)
| 操作 | 说明 |
|---|---|
CreateAutoScalingGroup | 创建组,支持 min/max/desired 容量、AZ、标签、启动配置/启动模板/混合实例策略;随即启动容量协调循环 |
DescribeAutoScalingGroups | 按名称过滤;返回实例列表(含生命周期状态)与混合实例策略形状 |
UpdateAutoScalingGroup | 更新容量边界、冷却时间、启动源、AZ |
DeleteAutoScalingGroup | ForceDelete=true时先终止全部实例再删除 |
创建时默认值处理:DefaultCooldown缺省为300,HealthCheckType缺省为EC2,TerminationPolicies缺省为["Default"](见 AutoScalingService.java)。删除组时若仍有存活实例且未设ForceDelete,会抛ResourceInUse;ForceDelete=true则逐一调用 EC2 终止接口,随后清理关联的钩子、策略、实例刷新、计划任务与 Warm Pool。
实例管理
| 操作 | 说明 |
|---|---|
DescribeAutoScalingInstances | 返回所有被 ASG 跟踪的实例及其生命周期与健康状态 |
SetDesiredCapacity | 更新期望数量;协调器在 10 秒内完成扩缩容 |
AttachInstances | 将已有 EC2 实例挂入组内,生命周期置为InService |
DetachInstances | 从组内摘除实例,可选是否递减 DesiredCapacity |
TerminateInstanceInAutoScalingGroup | 终止指定实例,可选递减 DesiredCapacity |
SuspendProcesses | 记录被挂起的扩缩进程(空列表表示挂起全部),DescribeAutoScalingGroups回显 |
ResumeProcesses | 清除挂起记录(空列表表示恢复全部) |
SetDesiredCapacity会校验新值必须落在[MinSize, MaxSize]区间内(见 AutoScalingService.java)。SuspendProcesses的"空列表挂起全部"语义对应 AWS 的 9 个标准进程:Launch、Terminate、AddToLoadBalancer、AlarmNotification、AZRebalance、HealthCheck、InstanceRefresh、ReplaceUnhealthy、ScheduledActions。源码注释明确指出:Terraform AWS Provider 在wait_for_capacity_timeout非零(默认值)时总会无条件调用SuspendProcesses,因此该操作若未实现会导致 ASG 创建整体失败——Floci 采用"接受并记录"策略保证兼容。
此外,Floci 还实现了SetInstanceProtection与SetInstanceHealth:前者标记实例protectedFromScaleIn(缩容候选会被过滤),后者校验健康状态只能是Healthy或Unhealthy。需注意源码注释提示:ShouldRespectGracePeriod参数仅做 wire 兼容解析,尚未真正对照HealthCheckGracePeriod生效。
负载均衡挂载
| 操作 | 说明 |
|---|---|
AttachLoadBalancerTargetGroups | 挂载 ELB v2 目标组 ARN;新实例 InService 时自动注册 |
DetachLoadBalancerTargetGroups | 摘除目标组;实例随之反注册 |
DescribeLoadBalancerTargetGroups | 列出组关联的目标组 |
AttachLoadBalancers | 经典 ELB 挂载(仅存储,不做 ELB v1 路由) |
DetachLoadBalancers | 经典 ELB 摘除 |
DescribeLoadBalancers | 列出组关联的经典 ELB |
目标组挂载会持久化到组的TargetGroupARNs列表;协调器在实例进入InService时调用ElbV2Service.registerTargets完成真实注册(见 AutoScalingReconciler.java),同时也会向经典 ELBregisterInstances注册(LoadBalancerNames与目标组是相互独立的两条链路,可同时存在)。
流量源(Traffic Sources)
| 操作 | 说明 |
|---|---|
AttachTrafficSources | 统一的 elb/elbv2/vpc-lattice 挂载 API,按 identifier 与 type 存储 |
DetachTrafficSources | 按 identifier 移除流量源 |
DescribeTrafficSources | 列出已挂载源,可按 type 过滤;每个源都报告InService |
源码将其实现为Map<identifier, type>,type 缺省为elbv2。Terraform 的aws_autoscaling_traffic_source_attachment使用该 API 而非旧的AttachLoadBalancerTargetGroups。由于 Floci 没有真实的健康检查循环,所有挂载的流量源立即上报InService——注释明确说明这是"接受并记住"模式。
生命周期钩子
| 操作 | 说明 |
|---|---|
PutLifecycleHook | 创建/更新钩子:LifecycleTransition、DefaultResult、HeartbeatTimeout |
DescribeLifecycleHooks | 列出组的钩子 |
DeleteLifecycleHook | 移除钩子 |
CompleteLifecycleAction | 对挂起的生命周期动作发出CONTINUE或ABANDON |
RecordLifecycleActionHeartbeat | 延长进行中动作的心跳超时 |
钩子名校验严格遵循 AWS 模型(autoscaling/2011-01-01/service-2.json):长度 ≤ 255,且必须匹配^[A-Za-z0-9\-_/]+$;LifecycleActionToken必须恰好 36 字符(见 AutoScalingService.java)。CompleteLifecycleAction当前为存储型实现,协调器通过实例生命周期状态间接观察结果。
扩缩策略与计划任务
| 操作 | 说明 |
|---|---|
PutScalingPolicy | 创建/更新策略:SimpleScaling字段或带预定义指标、目标值、预热时间的TargetTrackingScaling |
DescribePolicies | 按组或策略名过滤,回显存储的目标跟踪配置 |
DeletePolicy | 删除扩缩策略 |
PutScheduledUpdateGroupAction | 创建/更新计划:recurrence、时区、起止时间、容量边界 |
DescribeScheduledActions | 按组或动作名过滤 |
DeleteScheduledAction | 移除计划动作 |
策略 ARN 形如arn:aws:autoscaling:<region>:<account>:scalingPolicy:<group>:<policyName>。计划任务与策略一样采用"接受并记住"模式——Floci 没有真正的 cron 调度器去执行这些计划,但 Terraform Provider 的 Read 操作本就不期望模拟器内计划真的触发,因此足以支撑aws_autoscaling_schedule的完整生命周期(见 AutoScalingService.java 注释)。
Warm Pool 与活动日志
| 操作 | 说明 |
|---|---|
PutWarmPool | 按 wire 模型整体替换:省略字段重置为默认;MaxGroupPreparedCapacity=-1清除该值 |
DescribeWarmPool | 返回存储配置;同时嵌入DescribeAutoScalingGroups的 AutoScalingGroup 形状 |
DeleteWarmPool | 移除配置;不存在时幂等成功 |
DescribeScalingActivities | 返回组的活动日志;扩缩容事件均有记录 |
Warm Pool 的实现与 AWS 行为对齐:MinSize省略时默认0,PoolState省略时默认Stopped(省略字段重置为默认,而不是沿用旧值,因此putWarmPool总是从零重建配置);MaxGroupPreparedCapacity没有默认值,-1是 wire 模型文档化的"清除已设值"哨兵,映射回null而非渲染为-1。由于没有真正预热实例的循环,DescribeWarmPool的Instances列表恒为空(注释见 AutoScalingService.java)。
元数据类操作
以下操作返回标准枚举,用于支持 SDK/工具对能力边界的探测:
DescribeTerminationPolicyTypes:标准终止策略名DescribeAccountLimits:组的最大数量/配置/实例限额DescribeLifecycleHookTypes:autoscaling:EC2_INSTANCE_LAUNCHING与autoscaling:EC2_INSTANCE_TERMINATINGDescribeAdjustmentTypes:四种标准调整类型DescribeMetricCollectionTypes:标准指标与粒度名DescribeAutoScalingNotificationTypes:全部通知类型名
Capacity Reconciler:真实的扩缩容引擎
Floci 的 Auto Scaling 不是纯"记状态"模拟。AutoScalingReconciler在应用启动后以scheduleAtFixedRate(this::reconcileAll, 5, 10, TimeUnit.SECONDS)的方式每10 秒固定频率运行一轮(见 AutoScalingReconciler.java),单线程调度线程名为asg-reconciler。
每轮reconcile(asg)的执行顺序(AutoScalingReconciler.java):
- 移除终止中实例:将
Terminating状态实例从目标组/经典 ELB 反注册,调用TerminateInstances,再移除记录。 - 清除陈旧实例:
InService但底层 EC2 已不运行的实例、Pending但 EC2 已缺失或处于终止/停止状态的实例会被清理,同时将相关活跃 SSM 命令调用标记为Undeliverable。 - 清理孤儿目标注册:目标组中不属于任何活跃 ASG 实例的 target 会被反注册。
- 晋升就绪实例:
Pending状态的实例一旦 EC2 状态变为running,即晋升为InService并注册到所有已挂载目标组与经典 ELB。 - 容量对齐:统计
Pending+InService的活跃容量,与DesiredCapacity比较后执行扩缩。
扩缩逻辑(AutoScalingReconciler.java):
- Scale-out:解析启动源(启动配置 → 启动模板 → 混合实例策略,优先级依次降级),调用
RunInstances按需数量拉起实例,新实例以Pending状态入库;若组已删除导致保存失败,会回滚终止这些实例。AZ 选择:组配置了 AZ 则取第一个,否则用<region>a;子网同理取第一个。组标签中标记为"启动时传播"的标签会随实例下发。 - Scale-in:从
InService且未被protectedFromScaleIn保护的实例中选取,先反注册目标组与经典 ELB,再调用TerminateInstances并移除记录。 - 每次扩缩容事件都会写入一条活动记录(
recordActivity),供DescribeScalingActivities查询。
协调器对启动源做了精细处理(resolveLaunchSource):启动模板解析时会读取指定版本的ImageId、InstanceType、KeyName、安全组、实例标签、UserData 与 IAM 实例配置档;混合实例策略则取 override 中第一个显式InstanceType。启动模板被删除时,仅InvalidLaunchTemplateName.NotFoundException/InvalidLaunchTemplateId.NotFound被当作"模板已消失"而跳过该轮,其他异常会向上传播以免掩盖真实故障。
Launch Source 兼容性与混合实例策略
自动扩缩组只能保留三种启动源之一:启动配置、顶层启动模板、或MixedInstancesPolicy,在创建/更新请求中互斥。同时提供多个启动源会抛ValidationError("mutually exclusive")。混合实例策略存储并回显以下字段:
LaunchTemplate.LaunchTemplateSpecification.LaunchTemplateIdLaunchTemplate.LaunchTemplateSpecification.LaunchTemplateNameLaunchTemplate.LaunchTemplateSpecification.VersionLaunchTemplate.Overrides.member.N.InstanceTypeLaunchTemplate.Overrides.member.N.InstanceRequirementsInstancesDistribution.OnDemandBaseCapacityInstancesDistribution.OnDemandPercentageAboveBaseCapacityInstancesDistribution.SpotAllocationStrategy
override 选择实例类型的方式二选一:按名称(InstanceType)或按属性(InstanceRequirements)。规则(见 AutoScalingService.java):
- 同一 override 同时设置
InstanceType与InstanceRequirements抛ValidationError,与 AWS 一致; - 指定
InstanceRequirements时必须同时给出VCpuCount与MemoryMiB(AWS 模型在该 shape 上标记的必填成员),否则抛ValidationError; InstanceRequirements的所有成员均可往返(round-trip),唯一例外是BaselinePerformanceFactors——接受但丢弃。
属性型实例类型选择(attribute-based selection)的判定规则:当生效的混合实例策略中至少一个 override 携带InstanceRequirements时,该组使用属性型选择。创建时生效策略即请求提供的策略;更新时则是请求提供的策略、未指定启动源时存储的策略、或请求切换到启动配置/普通启动模板时的"无"。
可选组字段:何时回显、何时省略
CreateAutoScalingGroup与UpdateAutoScalingGroup都接受以下字段,而DescribeAutoScalingGroups仅在组设置了该字段时才回显——从未设置的字段从响应中省略,而非返回默认值(实现载体是 AsgOptionalFields.java):
| 字段 | 说明 |
|---|---|
DesiredCapacityType | 取值units、vcpu、memory-mib,其他值抛ValidationError。AWS 仅支持其用于属性型实例类型选择,因此vcpu/memory-mib在生效的混合实例策略未使用InstanceRequirements时抛ValidationError;units是文档化默认值,始终接受 |
CapacityRebalance | 布尔值,存储并原样回显 |
MaxInstanceLifetime | 秒。必须为0或至少86400;0表示无上限,回显为0 |
DefaultInstanceWarmup | 秒。传-1移除已设值,之后字段再次省略 |
更新语义是部分更新:请求未设置的成员不动存量值(applyToExistingGroup仅覆盖显式传入成员),而创建时未设置则直接不设置。DefaultInstanceWarmup的-1哨兵会被解析为null后省略,而不是存储-1。
扩缩策略兼容性
目标跟踪策略保留TargetTrackingConfiguration。DescribePolicies在配置存在时返回PredefinedMetricSpecification.PredefinedMetricType、TargetValue与EstimatedInstanceWarmup。PutScalingPolicy中PolicyType缺省为SimpleScaling,同时记录AdjustmentType、ScalingAdjustment与Cooldown,供下游工具完整读回。
配置开关
| 变量 | 默认值 | 说明 |
|---|---|---|
FLOCI_SERVICES_AUTOSCALING_ENABLED | true | 启用或禁用 Auto Scaling 服务 |
该配置对应EmulatorConfig.AutoScalingServiceConfig.enabled()(@WithDefault("true")),与其他服务模块(如 Application Auto Scaling)的开关模式一致。环境变量名由 Quarkus 的配置映射规则推导(floci.services.autoscaling.enabled属性对应的环境变量形式)。将其设为false可整体关闭该服务的 API 入口。
使用示例
以下是基于文档的完整演练,覆盖"创建启动配置 → 创建组 → 挂载目标组 → 观察实例 → 扩容"的全流程:
# 创建启动配置 aws autoscaling create-launch-configuration \ --launch-configuration-name my-lc \ --image-id ami-12345678 \ --instance-type t3.micro # 创建目标 desired=2 的组 aws autoscaling create-auto-scaling-group \ --auto-scaling-group-name my-asg \ --launch-configuration-name my-lc \ --min-size 1 \ --max-size 5 \ --desired-capacity 2 \ --availability-zones us-east-1a # 挂载 ELB v2 目标组 aws autoscaling attach-load-balancer-target-groups \ --auto-scaling-group-name my-asg \ --target-group-arns arn:aws:elasticloadbalancing:us-east-1:000000000000:targetgroup/my-tg/abc123 # 观察实例出现(Pending → InService,约 10 秒内完成) aws autoscaling describe-auto-scaling-groups \ --auto-scaling-group-names my-asg # 扩容 aws autoscaling set-desired-capacity \ --auto-scaling-group-name my-asg \ --desired-capacity 3创建组后约 5~10 秒内协调器开始工作:RunInstances拉起 2 个实例进入Pending,EC2 进入running后晋升InService并自动注册到目标组。扩容到 3 后,下一轮协调器会补 1 个实例;反向调低 desired 则触发缩容。若需调试,可配合aws autoscaling describe-scaling-activities --auto-scaling-group-name my-asg查看每次扩缩容的活动记录。
边界与限制
从源码注释可以确认以下已知边界(均为有意的"接受并记住"设计,而非缺陷):
CompleteLifecycleAction不实际执行 SNS 通知,仅做存储级校验(CONTINUE/ABANDON由协调器通过实例状态间接体现);- 计划任务与扩缩策略只有存储语义,不会真正按 cron 或指标触发扩容——真实扩容仅由
SetDesiredCapacity/ 容量边界变化驱动协调器完成; - Warm Pool 不预热实例,
DescribeWarmPool.Instances恒为空; - 经典 ELB 挂载只做存储与实例注册,不做真实流量路由;
ShouldRespectGracePeriod尚未与HealthCheckGracePeriod联动;BaselinePerformanceFactors接受后不保留。
这些边界覆盖了 AWS SDK、Terraform Provider 等主流工具在本地开发场景下的全部读回路径,使得基于 Floci 的 CI 流程可以无侵入地演练 ASG 的创建、扩容、缩容与销毁。
进一步阅读
- 服务实现主类:AutoScalingService.java
- 容量协调器:AutoScalingReconciler.java
- Query 协议分发:AutoScalingQueryHandler.java
- 可选字段模型:AsgOptionalFields.java
- 集成测试:AutoScalingIntegrationTest.java
- 协调器单元测试:AutoScalingReconcilerTest.java
- 官方服务文档:docs/services/autoscaling.md
【免费下载链接】floci
Light, fluffy, and always free - The AWS Local Emulator alternative
相关推荐
aws-cli 实战:用 `aws autoscaling set-desired-capacity` 手动调整 Auto Scaling 组容量
aws cli 实战:用 aws autoscaling set desired capacity 手动调整 Auto Scaling 组容量 导读 本篇文章围
开发工具云原生运维AWS CLI `autoscaling set-instance-protection` 实战指南:为 EC2 Auto Scaling 实例启用与关闭缩容保护
AWS CLI autoscaling set instance protection 实战指南:为 EC2 Auto Scaling 实例启用与关闭缩容保护
开发工具云原生运维AWS CLI 实战:使用 detach-instances 将 EC2 实例从 Auto Scaling 组分离(附源码解析)
AWS CLI 实战:使用 detach instances 将 EC2 实例从 Auto Scaling 组分离(附源码解析) aws autoscaling
开发工具云原生运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考