Envoy 移除 trace_refresh_after_route_refresh 运行时开关:路由刷新后 Trace 决策与 Decorator 永久刷新机制解析

Envoy 移除 trace_refresh_after_route_refresh 运行时开关:路由刷新后 Trace 决策与 Decorator 永久刷新机制解析 Envoy 移除 trace_refresh_after_route_refresh 运行时开关路由刷新后 Trace 决策与 Decorator 永久刷新机制解析【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy本文聚焦 Envoy 在最新版本changelogs/current对应版本中对 HTTP 连接管理器HTTP Connection ManagerHCM的一项变更正式移除运行时开关envoy.reloadable_features.trace_refresh_after_route_refresh及其守护的旧代码路径。路由刷新后HCM 将始终重新计算 trace 采样决策并应用新路由的 decorator同时统计信息统一由chargeStats路径上报。读完本文你将理解该开关引入的背景v1.36.0 行为变更、新行为的源码级实现细节、pack_trace_reason的边界注意事项以及升级时的迁移与验证要点。变更总览一个运行时开关的完整生命周期该变更记录在 tracing__trace-refresh-after-route-refresh.rst 中核心内容如下Removed the runtime guardenvoy.reloadable_features.trace_refresh_after_route_refreshand the legacy code path it guarded. The HTTP connection manager now always refreshes the trace decision and decorator when the route is refreshed, and charges the tracing statistics fromchargeStatsrather than from the old un-refreshed code path.即本次变更包含三件事删除运行时开关envoy.reloadable_features.trace_refresh_after_route_refresh从源码中彻底移除无法再通过设置其为false恢复旧行为固化新行为HCM 在路由被刷新route refresh时总是刷新 trace 决策trace decision与 decorator统一统计路径tracing 统计信息统一从chargeStats路径上报旧的未刷新代码路径被删除。背景这个开关为何存在要理解此次移除需要先回溯该开关的引入。在 changelogs/1.36.0.yaml 的behavior_changes一节中可以找到这条历史变更记录A route refresh will now result in a tracing refresh. The trace sampling decision and decoration of the new route will be applied to the active span. This change can be reverted by setting the runtime guardenvoy.reloadable_features.trace_refresh_after_route_refreshtofalse.也就是说在 Envoy 1.36.0发布于 2025 年 10 月 14 日中路由刷新后同步刷新 tracing作为一个默认开启但可回退的行为变更被引入默认启用新逻辑运维人员可通过运行时开关临时回退到旧逻辑。经过若干版本验证后在changelogs/current对应的版本中该开关被移除新行为成为唯一行为。什么是路由刷新在 Envoy 中路由刷新指已建立请求的活跃流ActiveStream在其生命周期内再次触发路由解析re-route并更新缓存路由的过程。典型场景包括HTTP 过滤器在请求处理中途通过recalculateRoute源码中对应ActiveStream::recalculateRoute见 conn_manager_impl.cc重新选择路由——例如基于 scoped RDS 的 scope 键头变化、或过滤器修改了路由相关头信息。刷新完成后源码会依次调用refreshTracing()—— 刷新 trace 决策与 decoratorrefreshDurationTimeout()—— 刷新基于路由的超时refreshIdleAndFlushTimeouts()—— 刷新空闲/冲刷超时refreshBufferLimit()—— 刷新缓冲上限。由此可见tracing 刷新只是路由刷新后一系列按新路由对齐流状态动作中的一环与超时、缓冲等逻辑处于同等地位。源码级解析refreshTracing() 到底做了什么本次移除开关后固化的核心逻辑位于ConnectionManagerImpl::ActiveStream::refreshTracing()实现在 conn_manager_impl.cc。该方法在执行前先做三项前置判断任一不满足则直接返回if (!connection_manager_tracing_config_.has_value() || active_span_ nullptr || request_headers_ nullptr) { return; } ASSERT(cached_route_.has_value());即未配置 HCM 级 tracing 配置、尚无活跃 span、或请求头不存在时无需刷新。随后按以下步骤完成刷新1. 重新计算 trace reason追踪原因const auto trace_reason ConnectionManagerUtility::mutateTracingRequestHeader( *request_headers_, connection_manager_.runtime_, *connection_manager_.config_, cached_route_.value().get()); filter_manager_.streamInfo().setTraceReason(trace_reason);mutateTracingRequestHeader定义于 conn_manager_utility.cc负责根据请求头如x-envoy-force-trace、运行时配置与路由配置判定该请求应被追踪的原因reason并将其写入StreamInfo。这保证路由刷新后 trace reason 反映的是新路由的配置。2. 重新做采样决策并应用到活跃 spanconst Tracing::Decision tracing_decision Tracing::TracerUtility::shouldTraceRequest(filter_manager_.streamInfo()); if (active_span_-useLocalDecision()) { active_span_-setSampled(tracing_decision.traced); }TracerUtility::shouldTraceRequest综合StreamInfo中的 trace reason、采样率配置等得出最终的Tracing::Decision是否追踪、以及追踪原因。若当前活跃 span 使用的是本地决策useLocalDecision()即未被外部注入决策强制覆盖则调用setSampled(traced)将新决策应用到 span 上。3. 刷新路由级 decorator 与 tracing 配置if (hasCachedRoute()) { route_decorator_ cached_route_.value()-decorator(); route_tracing_ cached_route_.value()-tracingConfig(); } if (!operationNameFormatter(*connection_manager_tracing_config_, route_tracing_)) { // Only set decorator when there is no operation name formatter configured at either // the HCM level or the route level. setRequestDecorator(*request_headers_); }这里将缓存路由的decorator()路由装饰器可为 span 设置 operation name与tracingConfig()重新赋值。需要注意一个细节仅当 HCM 级与路由级都未配置 operation name formatter 时才会调用setRequestDecorator将 decorator 应用到请求头与 span——否则以 formatter 生成的 operation name 为准。这避免了 decorator 与自定义操作名格式化器之间的冲突。setRequestDecoratorconn_manager_impl.cc 起会根据当前请求方向ingress/egress、是否覆盖装饰操作名decorator_overriden_、是否传播decorated_propagate_等状态决定是否把 decorator 的 operation name 写入x-envoy-decorator-operation响应头从而保证外部可观测系统如追踪后端看到的操作名与最新路由保持一致。统计路径统一为什么从 chargeStats 上报变更说明中特别强调tracing 统计信息charges the tracing statistics fromchargeStatsrather than from the old un-refreshed code path。ActiveStream::chargeStats(const ResponseHeaderMap headers)conn_manager_impl.cc是每个请求完成/产生响应头时统一执行统计上报的入口其 tracing 统计部分如下if (connection_manager_tracing_config_.has_value()) { const Tracing::Decision tracing_decision Tracing::TracerUtility::shouldTraceRequest(filter_manager_.streamInfo()); ConnectionManagerImpl::chargeTracingStats(tracing_decision.reason, connection_manager_.config_-tracingStats()); }它基于最终刷新后的 StreamInfo重新计算shouldTraceRequest决策再通过chargeTracingStats累加如tracing.random_sampling、tracing.service_required、tracing.client_enabled、tracing.not_traceable等统计。由于此时StreamInfo中的 trace reason 已在refreshTracing阶段被更新为新路由的判定结果因此上报的统计天然反映路由刷新后的最终决策不再需要旧的未刷新代码路径单独维护一份统计逻辑。这也是本次变更删除旧路径的动机消除双路径统计的不一致确保观测数据与真实追踪行为严格对齐。关键边界pack_trace_reason 与不可撤销的已追踪请求升级到新行为后有一个必须理解的边界它在 v1.36.0 的变更记录中已被明确标注并且在refreshTracing()的源码注释中也有对应说明NOTE: if the trace reason have been encoded into the request id then the trace reason may not be updated. That means we may cannot force a traced request to be untraced by the refreshing.见 conn_manager_impl.cc 的注释这与 UUID 请求 ID 扩展中的pack_trace_reason配置相关定义于 uuid.protogoogle.protobuf.BoolValue pack_trace_reason 1;当pack_trace_reason为true默认值时trace reason 会被编码进请求 IDx-request-id中并随请求传播到上游。由于 reason 已固化在请求 ID 里即使路由刷新后新路由判定不应采样已被标记为 traced 的请求也无法在刷新后被取消标记unmarked。反之如果pack_trace_reason设置为false则 trace reason 不写入请求 ID刷新后存在将请求从 traced 调整为 untraced 的可能。因此在规划依赖该行为的使用场景时需要明确若pack_trace_reason保持默认true路由刷新只能从 untraced 变为 traced或保持 traced 不变不能反向撤销已追踪请求若你的场景依赖刷新后撤销追踪需要显式设置pack_trace_reason: false但需自行评估请求 ID 不再携带 trace reason 对端到端传播的影响。升级影响与迁移检查清单由于运行时开关已被移除任何依赖旧行为的配置都将失效。建议按以下清单核查搜索运行时开关引用在配置与代码中检索envoy.reloadable_features.trace_refresh_after_route_refresh。当前仓库源码中该字符串仅存在于变更记录文件tracing__trace-refresh-after-route-refresh.rst 与历史版本 1.36.0.yaml中source/目录已无任何引用说明该开关从代码层面已彻底下线。若你的运行配置中显式设置过该开关升级后它会被忽略建议删除以免产生误导。确认依赖的追踪语义若此前依赖路由刷新后不刷新 trace 决策的旧行为例如路由中途切换后仍按原路由采样升级后采样行为将变化需在测试环境先行验证。检查统计口径变化tracing 统计改由chargeStats统一上报后旧路径对应的统计计数将不再产生监控告警若按旧口径设定阈值需同步调整。评估 pack_trace_reason 影响若在UuidRequestIdConfig中启用了默认的pack_trace_reasontrue注意刷新后无法撤销已 traced 请求相关 A/B 或抽样策略需据此设计。如何验证新行为可以通过以下方式验证路由刷新后的 trace 行为配置基于 scoped RDS 或可动态变更的路由配置配合会在请求中途修改路由相关头如 scope key的 HTTP 过滤器观察请求在路由刷新前后的采样结果变化开启 tracing 统计tracing: random_sampling等后对比chargeStats路径上报的统计与最终 span 的采样状态是否一致验证统计与追踪行为的对齐针对pack_trace_reason两种取值分别验证true时确认已 traced 请求刷新后保持 tracedfalse时确认刷新后决策可被更新甚至可以反向撤销。小结envoy.reloadable_features.trace_refresh_after_route_refresh的移除标志着路由刷新后同步刷新 trace 决策与 decorator从可回退的行为变更正式演变为Envoy 的固有语义。从源码看refreshTracing()以重新计算 trace reason → 重新决策采样 → 应用新路由 decorator三步完成刷新并直接作用于活跃 span 与请求头统计则统一收敛到chargeStats消除了双路径统计的不一致。对于使用者而言升级后只需重点关注pack_trace_reason带来的已追踪请求不可撤销边界以及统计口径的切换即可平滑迁移。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考