弹性扩缩容-FIFO 队列最佳实践
- 服务端处理能力受限,不支持并发处理多个请求,同一时间只能执行一个任务。
- 需要保证请求严格按照到达顺序进行处理(FIFO),避免请求乱序执行导致的数据一致性或业务逻辑问题。
- 需要根据业务负载动态调整任务节点数量,在资源成本与系统处理能力之间实现平衡。
1.环境准备
Section titled “1.环境准备”需要准备一个带宽充足的云服务器,安装好 docker 环境。
如果只是本地测试使用,则不需要云服务器,只需要在本地安装好 docker 环境即可。
2.配置文件填写
Section titled “2.配置文件填写”完整的配置文件如下:
{ "openapi_base_url": "https://openapi.suanli.cn", //共绩域名,固定 "token": "", // 用户密钥,用于调用共绩云 API 增减节点 "min_nodes": 1, //节点池最少保留的节点数,即使空闲也不会缩容到该值以下。可设为 `0`:允许缩容到 0,启动时不预创建任务,有请求时再冷启动。 "max_nodes": 3, //节点池最多允许创建的节点数,扩容时不会超过该上限。 "max_scale_down_nodes": 1, //单次缩容最多同时关闭的节点数,避免一次性关闭过多节点。 "scale_down_cooldown_secs": 180, // 两次缩容之间的最小间隔,避免短时间内反复关闭节点。 "queue_scale_wait_secs": 120, //请求队列超过阈值后,需要持续等待的秒数才触发扩容。 "queue_scale_count_threshold": 10, //触发扩容的队列长度阈值。 "idle_shutdown_secs": 180, //节点连续空闲超过该秒数后,会被关闭以释放资源。 "scale_up_cooldown_secs": 30, //两次扩容之间的最小间隔,避免短时间内反复创建节点。 "node_refresh_interval_secs": 15, //刷新节点状态的时间间隔。 "scale_check_interval_secs": 5, //检查是否需要扩缩容的时间间隔。 "stats_log_interval_secs": 15, //输出统计日志的时间间隔。 "proxy_port": 3000, //实际需要代理转发请求的容器端口,例如 3000。 "health_check_path": "/ready", //健康检查(就绪)接口路径,用于判断节点是否可用。 "scale_up_request": { //调用上游 API 创建新节点时的请求模板 "task_name": "gjtest-comfyui", //创建任务使用的任务名称前缀,不支持下划线(_),注意同账号下以该任务名称开头的任务,均将视为同一组任务节点池,会受本程序管控。 "points": 1, //创建的任务内有多少个节点,固定 1 个、便于本程序调度。 "resources": [ { "mark": "" // `mark` 标识一组资源配额,可以通过分析控制台 search 接口返回值查找其它区的 mark 值。 } ], "services": [ // 节点中运行的服务列表(容器配置信息)。 { "service_name": "container-01", //服务名称。 "service_image": "", //服务使用的容器镜像。 "remote_ports": [ //服务对外暴露的端口列表。 { "service_port": 3000 }, { "service_port": 8188 } ], "start_script_v2": { //服务启动参数与命令。 "args": [], "command": null }, "storage_config": [ //服务挂载的存储配置。可为空 { "storage_id": 2451, "target_dir": "/opt/ComfyUI/models" } ] } ] }}大多数配置默认值即可满足需求,需要重点关注的配置为:
- token:用户 token,可在平台控制台获取
- min_nodes:最小节点数
- max_nodes:最大节点数
- proxy_port:该服务需要被转发的端口
- health_check_path:该服务提供的健康监测路径,只有该路径返回状态码 200 时,才认为该任务可用、才会被转发请求
- scale_up_request:创建任务的配置
- mark:创建任务使用的资源配额标识。
3.部署服务
Section titled “3.部署服务”docker run -d -v [配置文件]:/app/config.json -p 8080:8080 harbor.suanleme.cn/vm/gj_proxy:v0.6注意将命令中的中文替换为正确的文件路径。
部署成功后,所有打入该服务的流量将进入排队,只有当后端任务处于空闲时、才会将请求转发给该任务进行处理,保证后端每个任务最多同时只会接收到一个请求。
本服务会对请求进行排队,所有进入的用户流量都会先进入队列,等待后端任务空闲,保证每个后端任务同一时间只处理一个用户请求。
2.扩缩容规则
Section titled “2.扩缩容规则”-
触发条件:当请求队列非空,且满足以下任一条件时触发扩容:
- 冷启动:当前无节点且无创建中任务(
min_nodes=0缩容到 0 后,或启动时未预创建); - 等待触发:队列中最久的请求等待时间达到
queue_scale_wait_secs秒; - 数量触发:队列长度超过
queue_scale_count_threshold。
- 冷启动:当前无节点且无创建中任务(
-
冷却限制:如果距上次扩容时间不足
scale_up_cooldown_secs秒,跳过本次扩容,避免短时间内反复创建节点。冷启动不受此冷却限制。 -
上限保护:扩容后的总节点数(当前就绪节点 + 正在创建中的节点 + 本次新增节点)不能超过
max_nodes。如果当前节点数加上正在创建的节点数已达max_nodes,则本次扩容不会执行。 -
扩容数量:本次扩容数量取
max(队列长度 / 2, 1),并同时受max_nodes剩余可用槽位限制;如果计算值大于可用槽位,则按可用槽位扩容。
-
触发条件:当节点池中存在满足以下条件的节点时,会被列为缩容候选:
- 请求队列为空(有排队请求时不缩容);
- 节点当前处于空闲状态(没有正在处理的请求);
- 该节点最近一次处理完请求后,空闲时间已超过
idle_shutdown_secs秒。
-
冷却限制:如果距上次缩容时间不足
scale_down_cooldown_secs秒,跳过本次缩容,避免频繁关闭节点。 -
下限保护:就绪节点数必须至少保留
min_nodes个,即使这些节点空闲也不会被缩容。程序只会缩容“超出min_nodes数量的就绪节点”。min_nodes=0时允许缩容到 0。未就绪的空闲节点在达到下限时仍可被清理。 -
单次上限:每次缩容最多关闭
max_scale_down_nodes个节点,避免一次性关闭过多节点导致服务能力骤降。 -
优先顺序:优先缩容最早进入空闲状态的节点(按节点最近一次处理请求的时间
last_processed从早到晚排序)。