ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Envoy 上游负载均衡慢启动模式(Slow Start)原理解析与配置实战

Envoy 上游负载均衡慢启动模式(Slow Start)原理解析与配置实战 Envoy 上游负载均衡慢启动模式Slow Start原理解析与配置实战【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy本篇指南围绕 Envoy 上游集群的慢启动Slow Start机制展开它如何让新加入集群的上游端点在有限窗口内逐步获得流量从而避免未预热服务被瞬时打满。读完本文你将理解slow_start_window、aggression、min_weight_percent三个核心参数的作用与取值逻辑掌握权重随时间增长的数学模型并能结合 Envoy 源码EdfLoadBalancerBase验证端点进出慢启动状态的判定逻辑最终在 Kubernetes 等动态扩缩容场景中做出合理的配置决策。为什么需要慢启动新端点的预热问题当新的上游端点加入 Envoy 集群时如果没有任何额外机制负载均衡算法会立即按权重比例向其发送流量。对于需要先完成预热例如 JIT 编译、缓存填充、连接池建立才能承载完整生产负载的服务而言这会导致请求超时、数据丢失和用户体验劣化。Envoy 通过慢启动模式解决这一问题它本质上是一种作用于负载均衡权重的机制按上游集群cluster粒度配置在端点加入后的指定时间窗口内将其有效权重从低值逐步放大到原始权重从而使流量随时间平滑爬坡。该机制对少量新端点陆续加入的场景例如 Kubernetes 的水平扩缩容事件最为有效而当所有端点都是新的例如一次全新部署时由于所有端点最终获得的请求量相同慢启动的实际收益有限——这一点在官方架构文档 slow_start.rst 中被明确强调配置时需要根据端点变更模式判断是否启用。配置入口三种负载均衡策略支持慢启动从 API 定义看慢启动目前支持三种负载均衡策略且配置均为按策略挂载而非全局开关Round Robin轮询通过Cluster.RoundRobinLbConfig.slow_start_config配置Least Request最少请求通过Cluster.LeastRequestLbConfig.slow_start_config配置Client-side Weighted Round Robin客户端加权轮询通过其策略 proto 中的slow_start_config字段配置。慢启动配置的消息体是envoy.extensions.load_balancing_policies.common.v3.SlowStartConfig定义见 common.proto包含三个字段字段类型默认值说明slow_start_windowgoogle.protobuf.Duration未设置即不启用单个端点慢启动窗口的时长。自端点创建或恢复健康起在该时长内端点处于慢启动模式aggressionRuntimeDouble1.0控制窗口内流量增长速度且是非线性的值必须大于 0。默认 1.0 时端点获得线性增长的流量调大该值可得到多项式或指数型的爬坡曲线min_weight_percenttype.v3.Percent10%慢启动期间有效权重相对于原始权重的下限百分比保证 EDF 调度器拥有合理的 deadline避免端点因权重过小长时间收不到任何请求在传统的 Cluster 配置中RoundRobinLbConfig与LeastRequestLbConfig各自内嵌了一份SlowStartConfig见 cluster.proto。两份SlowStartConfiglegacy 版与 extensions 版字段完全一致当使用新的load_balancing_policy配置方式时Envoy 会通过 LoadBalancerConfigHelper::convertSlowStartConfigTo 将旧字段逐项转换为新字段保证两种配置路径行为一致。一个启用慢启动的 Round Robin 集群示例如下基于上表参数注释补齐clusters: - name: origin_service type: EDS lb_policy: ROUND_ROBIN lb_config: round_robin_lb_config: slow_start_config: slow_start_window: 60s # 慢启动窗口端点加入后 60 秒内权重渐进放大 min_weight_percent: 10 # 慢启动期间有效权重不低于原始权重的 10% aggression: 1.0 # 线性爬坡1.0 变为加速非线性爬坡需要注意slow_start_config未设置时慢启动不会启用proto 注释明确If this configuration is not set, slow start will not be enabled且slow_start_window必须为正时长——源码中 isSlowStartEnabled 的判断就是slow_start_window_ 0。权重计算模型时间因子与 aggression在慢启动窗口内特定端点的负载均衡权重会按时间因子缩放官方文档给出的公式为NewWeight Weight * max(MinWeightPercent, TimeFactor ^ (1 / Aggression)) TimeFactor max(TimeSinceStartInSeconds, 1) / SlowStartWindowInSeconds各要素的含义与源码印证TimeFactor端点进入健康状态后的经过时间与窗口时长的比值。由于分子取max(..., 1)端点创建瞬间时间因子至少为 1/窗口权重立即被压到较低水平随后随时间单调上升直至窗口结束、恢复原始权重Aggression以1/Aggression为指数作用于时间因子。Aggression 为 1 时权重线性增长Aggression 大于 1 时曲线呈前快后慢的凹形加速小于 1 则相反。proto 注释中给出的等价表达式new_weight weight * max(min_weight_percent, time_factor ^ (1 / aggression))与文档公式一致见 common.protoMinWeightPercent对缩放结果设置下限。窗口极早期、或流量很低导致端点长时间未命中时该下限保证端点仍保有可被 EDF 调度器选中的权重。官方文档还给出了不同 aggression 取值下流量爬坡曲线的仿真图以及同优先级、无主动健康检查、60 秒窗口、aggression1.0场景下端点最终负载均衡权重的示例图E1、E2 两个端点退出慢启动后权重保持恒定而 E3 在加入后的 60 秒内权重持续爬升对应文档中的/_static/slow_start_aggression.svg与/_static/slow_start_example.svg两张图位于文档目录静态资源中。源码深潜慢启动权重如何被应用慢启动逻辑集中在 load_balancer_impl.cc 的EdfLoadBalancerBase中Round Robin 与 Least Request 都继承自它。核心调用链如下1. 端点进入慢启动状态的登记。负载均衡器订阅了PrioritySet的更新回调每当有主机加入member_update_cb_若慢启动已启用便调用 recalculateHostsInSlowStart。该方法的关键判定// Host enters slow start if only it has transitioned into healthy state. if (host-coarseHealth() Upstream::Host::Health::Healthy) { auto host_last_hc_pass_time host-lastHcPassTime() ? host-lastHcPassTime().value() : current_time; ... if (!host-lastHcPassTime()) { host-setLastHcPassTime(std::move(current_time)); }这印证了文档的进入规则未配置主动健康检查的集群端点加入时以当前时间初始化lastHcPassTime作为慢启动起点配置了主动健康检查的集群则以健康检查从 unhealthy 转 healthy 的时间为起点。慢启动窗口的计时基准始终是健康状态持续时间而非主机创建时间。2. 权重缩放的实际计算。applySlowStartFactor 实现了文档公式if (in_healthy_state_duration slow_start_window_) { double aggression aggression_runtime_ ! std::nullopt ? aggression_runtime_.value().value() : 1.0; if (aggression 0.0 || std::isnan(aggression)) { ENVOY_LOG_EVERY_POW_2(error, Invalid runtime value provided for aggression parameter, aggression cannot be less than 0.0); aggression 1.0; } auto time_factor static_castdouble(std::max(std::chrono::milliseconds(1).count(), in_healthy_state_duration.count())) / slow_start_window_.count(); return host_weight * std::max(applyAggressionFactor(time_factor, aggression), slow_start_min_weight_percent_); } else { return host_weight; }两个实现细节值得注意其一aggression支持 Runtime 动态值若运行时值非法小于等于 0 或 NaN会回退到 1.0 并记录错误日志其二健康状态持续时间超过窗口后直接返回原始权重对应窗口耗尽即退出慢启动的规则。3. 退出与再进入。从源码结构看退出慢启动由三类事件驱动端点离开集群PrioritySet移除回调触发refresh、健康状态不再为 HealthyapplySlowStartFactor中coarseHealth()判断不通过即返回原始权重、以及窗口自然耗尽。若端点之后再次通过主动健康检查恢复健康会以新的lastHcPassTime重新进入慢启动——与文档中unhealthy to healthy via active healthcheck 可重新进入慢启动的描述一一对应。4. 性能优化无慢启动时跳过 EDF 调度器。在 refreshHostSource 中存在一条快速路径若所有原始权重相等且没有端点处于慢启动状态则跳过 EDFEarliest Deadline First调度器构建退化为更省内存与 CPU 的无权重主机选择。这意味着启用慢启动的集群在慢启动期间必须维护 EDF 调度结构这是该机制的隐含成本。适用场景与已知局限文档明确警告低流量或端点数量极多的场景不建议启用慢启动潜在代价有两类端点饥饿Endpoint starvation流量过低或总端点过多时单个慢启动端点被选中的概率很低可能在窗口内几乎收不到请求非渐进的流量突增Spurious increase饥饿端点一旦收到请求、且窗口内已过去足够时间其时间因子已较大权重会因时间因子而非负载平滑度发生非线性跳升违背慢启动的初衷。此外还有两个边界行为需要知晓同样来自文档 slow_start.rst多优先级priority场景低优先级只有一个端点 A 时跨优先级 spillover 发生时流量会一次性全部切给 A没有渐进过程本地ity 加权负载均衡场景跨 zone 路由到只有一个端点 A 的 zone 时同样不存在流量渐进增长。小结Envoy 慢启动是一个轻量但设计严谨的端点预热机制以slow_start_window定义窗口、aggression控制爬坡形状、min_weight_percent兜底防止饥饿三者共同决定端点权重从低到高的时间曲线。配置入口位于各负载均衡策略的slow_start_config字段Round Robin / Least Request / Client-side WRR实现统一落在EdfLoadBalancerBase的recalculateHostsInSlowStart与applySlowStartFactor中并以健康检查通过时间作为窗口计时基准。在 Kubernetes 少量 Pod 扩容的场景下收益明显而在整体冷启动、超低流量或超大端点集合的场景下应结合端点饥饿与权重突增两个风险审慎评估是否启用。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表