资讯动态

Envoy 负载均衡器批量更新合并重建(coalesce_lb_rebuilds_on_batch_update)默认开启:原理、源码与配置指南

发布时间:2026/9/12 17:37:19 来源:尧图企业网站定制
Envoy 负载均衡器批量更新合并重建coalesce_lb_rebuilds_on_batch_update默认开启原理、源码与配置指南【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy导读本篇文章聚焦 Envoy 的一项运行时特性变更envoy.reloadable_features.coalesce_lb_rebuilds_on_batch_update现在默认开启true。该变更让线程感知型负载均衡器如RING_HASH、MAGLEV在批量主机host更新时只在批次结束时的单个MemberUpdateCb回调中重建一次 factory 状态而不是在每个优先级的更新回调中重复重建。读完本文你将理解 Envoy 主机更新的回调机制、该特性的源码实现与触发条件、测试如何验证其行为以及如何通过 bootstrap 运行时配置回退到旧行为。一、变更概述一次批处理只重建一次工厂状态按 changelogs/current/minor_behavior_changes/upstream__coalesce-lb-rebuilds-on-batch-update.rst 的说明The runtime guardenvoy.reloadable_features.coalesce_lb_rebuilds_on_batch_updatenow defaults totrue. A thread-aware load balancer (for exampleRING_HASHorMAGLEV) rebuilds its factory state once at the end of a batch host update, from the single end-of-cycle member-update callback, instead of once per priority from the per-priority update callback. The rebuild still lands before the cluster manager posts the update to the worker threads, so this only removes the redundant per-priority rebuilds of a batch.核心结论有三点默认值翻转该运行时开关由false变为true即新行为默认生效重建次数减少线程感知型负载均衡器thread-aware load balancer在一个批量主机更新batch host update期间从每个优先级各重建一次变为整批只在结束时重建一次时序安全不受影响重建仍然发生在 cluster manager 将更新投递post到 worker 线程之前因此只是消除了批次内冗余的逐优先级重建不改变数据一致性语义。若出现异常可通过将envoy.reloadable_features.coalesce_lb_rebuilds_on_batch_update显式设为false回退到旧行为。二、背景Envoy 中主机更新的回调机制要理解这次变更先要掌握PrioritySet上两种更新回调的区别对应源码 source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc 中的注释PriorityUpdateCb逐优先级回调每当某一个优先级priority如 EDS 中的 P0、P1、P2的主机集合发生变化时触发一次批量更新里会按优先级触发多次MemberUpdateCb成员更新回调在一次批量主机更新结束时只触发一次是端到端end-of-cycle的回调。线程感知型负载均衡器ThreadAwareLoadBalancerBase采用主线程构建 factory 状态、worker 线程快照使用的模式主线程通过refresh()重建 factory 状态例如 ring hash 的环、maglev 的查找表worker 线程从 factory 快照读取最新的负载均衡结构refresh()必须赶在 cluster manager 把对应主机更新投递给 worker 线程之前完成否则 worker 可能醒来后快照到过期的 factory代码注释中明确引用了对应的 issue #45055。因此ThreadAwareLoadBalancerBase在自己的PriorityUpdateCb中执行refresh()因为该回调注册在 cluster manager 的投递回调之前可以保证refresh()先于跨线程投递执行。旧行为的问题在批量主机更新batch host update场景下PriorityUpdateCb会按优先级反复触发每个优先级一次导致 factory 状态在一个批次内被重复重建 N 次N 涉及更新的优先级数量而这些中间状态最终都会被批次结束时的状态覆盖属于纯粹的冗余计算。三、变更的源码级实现3.1 运行时开关的定义该开关在 source/common/runtime/runtime_features.cc 中注册RUNTIME_GUARD(envoy_reloadable_features_coalesce_lb_rebuilds_on_batch_update);根据该文件头部的注释第 30-32 行RUNTIME_GUARD默认即为true即新代码路径默认被启用若需默认关闭则使用FALSE_RUNTIME_GUARD。本次变更正是将该 guard 从默认关闭改为默认开启。3.2 线程感知负载均衡器的合并逻辑thread_aware_lb_impl.cc 中ThreadAwareLoadBalancerBase::initialize()的实现如下const bool coalesce_lb_rebuilds Runtime::runtimeFeatureEnabled( envoy.reloadable_features.coalesce_lb_rebuilds_on_batch_update); const bool batch_aware_update Runtime::runtimeFeatureEnabled(envoy.reloadable_features.enable_batch_aware_update); const bool defer_refresh_during_batch coalesce_lb_rebuilds batch_aware_update; priority_update_cb_ priority_set_.addPriorityUpdateCb( this, defer_refresh_during_batch { // Refresh eagerly here if we didnt enable coalescing or the batch-aware update. if (!defer_refresh_during_batch) { processDirtyPriorities(); refresh(); } }); member_update_cb_ priority_set_.addMemberUpdateCb( this, defer_refresh_during_batch { // If we enabled coalescing and the batch-aware update... if (defer_refresh_during_batch) { processDirtyPriorities(); refresh(); } });需要特别注意的是延迟刷新defer并非只依赖本开关而是由两个开关共同决定coalesce_lb_rebuilds_on_batch_update为false时无论是否处于批量更新中都从PriorityUpdateCb立即刷新enable_batch_aware_update该开关让 cluster manager 将整个批次作为一次跨线程更新在批次结束时统一投递来自注册在本负载均衡器之后的MemberUpdateCb。代码注释明确指出只有在两个开关同时开启时延迟刷新才是安全的defer_refresh_during_batch coalesce_lb_rebuilds batch_aware_update。因为只有投递也被延迟到批次结束时主线程把重建也推迟到批次结束才不会被 worker 线程插队读到中间状态。此外initialize()还处理了一个边界情况如果initialize()在批量更新过程中被调用例如 EDSbatchUpdate - updateHosts(P0) - updateHosts(P1) - onPreInitComplete - initialize()的时序PriorityUpdateCb可能先于initialize()触发、而MemberUpdateCb被推迟到批次结束此时需要先processDirtyPriorities()处理已排队的优先级确保per_priority_panic_覆盖当前全部优先级再执行refresh()。3.3 非线程感知负载均衡器的同类处理这次变更不仅覆盖ThreadAwareLoadBalancerBase同样作用于其他基于PrioritySet回调的负载均衡基类它们全部采用PriorityUpdateCb记录脏优先级、MemberUpdateCb统一刷新的模式load_balancer_impl.cc 中LoadBalancerBase构造函数开启时PriorityUpdateCb只做dirty_priorities_.insert(priority)由MemberUpdateCb调用processDirtyPriorities()一次性重算所有脏优先级含 panic 模式重算、stashed_random_清理关闭时则走旧的逐优先级立即重算路径同文件 L458-L489 的ZoneAwareLoadBalancerBase开启时延迟执行 locality 权重 WRR 重建与 locality 路由结构再生成同文件 L977-L992 的EdfLoadBalancerBase如LEAST_REQUEST开启时PriorityUpdateCb记录脏优先级MemberUpdateCb逐个refresh(priority)重建调度器后统一dirty_priorities_.clear()再处理 slow start 相关逻辑。由此可见该特性对负载均衡器体系是横切的凡是依赖PriorityUpdateCb逐优先级重建内部结构的负载均衡实现都受益于本次合并。四、测试验证行为如何被证明仓库测试从正反两个方向验证了该特性可以作为你自行验证时的参考。4.1 重建次数对比测试thread-awaretest/extensions/load_balancing_policies/ring_hash/ring_hash_lb_test.cc 中定义了一个RefreshCountingLoadBalancer通过统计createLoadBalancer()被调用的次数来间接衡量refresh()次数refresh()对每个优先级调用一次createLoadBalancer()BatchUpdateCoalescesRefreshWhenBothFlagsEnabled两开关均开启一次涉及 P0、P1 的批量更新后create_count_为 2即一次合并刷新 × 两个优先级——工厂只重建了一次BatchUpdateRefreshesPerPriorityWhenCoalesceDisabledcoalesce_lb_rebuilds_on_batch_updatefalse同样的批量更新产生create_count_ 4即两次逐优先级刷新 × 每个刷新重建两个优先级——冗余重建清晰可见BatchUpdateRefreshesPerPriorityWhenBatchAwareDisabled仅开启合并开关、关闭enable_batch_aware_update同样不合并证明两个开关缺一不可。4.2 回退路径与中途初始化测试ring_hash_lb_test.cc L1161-L1192RingHashCoalesceDisabledTest.FallbackPathExercised在开关为false时验证旧的逐优先级刷新路径仍可正常工作ring_hash_lb_test.cc L1194-L1259RingHashMidBatchInitializeCrashTest模拟在批量更新过程中调用initialize()先 P0、P1 更新再onPreInitComplete验证开启合并后不会因新优先级出现而产生越界访问test/extensions/load_balancing_policies/least_request/least_request_lb_test.ccEdfLbCoalesceDisabledTest与EdfLbCoalesceEnabledTest分别验证LEAST_REQUEST负载均衡器在开关关闭回退路径与开启合并路径含 slow start 场景下的行为test/extensions/load_balancing_policies/common/load_balancer_impl_base_test.cc覆盖LoadBalancerBase在两种开关取值下processDirtyPriorities()的刷新语义。五、如何配置查看与回退5.1 默认状态当前仓库中该开关已通过RUNTIME_GUARD默认开启true无需任何配置即生效。你可以通过 Envoy 的/runtime管理接口或日志中的 runtime 层查看实际生效值。5.2 回退到旧行为若在升级后遇到与负载均衡刷新行为相关的问题例如希望恢复逐优先级立即刷新以缩小单次重建的计算窗口可在 bootstrap 配置中通过 layered runtime 的 static layer 显式覆盖runtime: symlink_root: /srv/runtime/current subdirectory: envoy layers: - name: static_layer_0 static_layer: envoy: reloadable_features: coalesce_lb_rebuilds_on_batch_update: false同样地如需确保批量感知投递关闭这将使延迟刷新完全不生效可一并设置envoy: reloadable_features: coalesce_lb_rebuilds_on_batch_update: false enable_batch_aware_update: false注意如前文源码分析所述coalesce_lb_rebuilds_on_batch_update与enable_batch_aware_update需同时开启才产生合并效果若你出于排查目的关闭了enable_batch_aware_update合并行为也会随之失效。六、影响范围与注意事项哪些负载均衡器受影响所有继承ThreadAwareLoadBalancerBase的实现如RING_HASH、MAGLEV以及使用LoadBalancerBase、ZoneAwareLoadBalancerBase、EdfLoadBalancerBase的实现如LEAST_REQUEST、ROUND_ROBIN等。判断某个负载均衡器是否走该路径可查看其类是否继承自上述基类。性能收益在涉及多个优先级的批量主机更新如 EDS 批量推送、健康检查状态翻转引发的大批主机变化中工厂重建次数从 O(优先级数) 降为 O(1)消除了批次内被中间状态覆盖的冗余计算。从源码结构看优先级越多、批量更新越频繁收益越明显。时序语义不变合并后的重建仍发生在 cluster manager 向 worker 线程投递更新之前得益于回调注册顺序负载均衡器的MemberUpdateCb注册在 cluster manager 的投递回调之前因此 worker 线程不会观察到新主机 旧工厂的不一致组合。前提条件合并生效依赖enable_batch_aware_update同时开启该开关在 runtime_features.cc 中同样是默认开启的RUNTIME_GUARD。若你通过配置覆盖关闭了它本特性的合并效果将不生效。回退与升级本变更属于 minor behavior change行为优化非破坏性变更默认开启的新路径有对应用例覆盖含回退路径测试。如生产环境遇到问题可参考本文第五节配置回退并及时反馈给社区。参考资料仓库内变更说明changelogs/current/minor_behavior_changes/upstream__coalesce-lb-rebuilds-on-batch-update.rst运行时开关注册source/common/runtime/runtime_features.cc线程感知负载均衡器实现source/extensions/load_balancing_policies/common/thread_aware_lb_impl.cc负载均衡基类实现source/extensions/load_balancing_policies/common/load_balancer_impl.cc相关测试ring_hash_lb_test.cc、least_request_lb_test.cc、load_balancer_impl_base_test.cc【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价