Envoy Stateful Session 过滤器全解析:基于可扩展会话状态实现强会话粘性

发布时间:2026/9/13 2:25:09
Envoy Stateful Session 过滤器全解析:基于可扩展会话状态实现强会话粘性 Envoy Stateful Session 过滤器全解析基于可扩展会话状态实现强会话粘性【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy导读Envoy 的 Stateful Session有状态会话HTTP 过滤器允许基于可扩展的会话状态Session State覆盖最终选择的上游主机并将最终选中的上游主机写回会话状态从而在不依赖哈希负载均衡的前提下实现强会话粘性strong stickiness。本文以官方文档 stateful_session_filter.rst 为主线结合仓库中的 proto 定义、示例配置与 C 源码实现系统讲解该过滤器的工作原理、Cookie/Header 两种会话状态扩展的配置方法、严格模式strict的行为差异以及统计指标体系帮助你在一线接入网关或网格代理中正确启用并运维这一能力。什么是 Stateful Session从弱粘性到强粘性会话粘性Session Stickiness的核心诉求是属于同一会话Session的请求应被一致地路由到同一个上游主机。Envoy 中传统的实现方式是哈希负载均衡Hash-based Load Balancing如envoy.lb_policy.maglev、envoy.lb_policy.ring_hash。但哈希粘性被认为是弱粘性——因为粘性建立在主机集合Host Set的哈希映射上一旦上游主机集合发生变化扩缩容、摘除等原有会话就可能被重新映射到不同的主机。Stateful Session 过滤器实现的是强粘性会话状态中显式记录该会话应去往哪个上游主机后续请求直接按记录的主机路由。原文档指出它主要面向两类场景需要更稳定粘性的场景例如某主机已被标记为 degraded降级但仍希望现有会话继续路由到该主机此时哈希负载均衡会因为健康检查或主机集合变化而改变映射。使用非哈希负载均衡器却仍需要粘性的场景例如使用 Random、Round Robin 等负载均衡策略时新会话按负载均衡结果选择上游主机而既有会话固定路由到会话记录的主机。从源码看该过滤器通过decoder_callbacks_-setUpstreamOverrideHost(...)将会话解析出的上游地址注入负载均衡上下文实现对负载均衡结果的覆盖override且覆盖优先级高于负载均衡本身的选择见 stateful_session.cc。安全与可靠性提醒原文档特别给出note警告Stateful Session 可能导致上游之间负载不均衡并可能允许外部参与者将请求定向到特定的上游主机。因此在启用该功能前运维人员必须仔细评估其安全性与可靠性影响——它本质上是把路由决策的一部分控制权交给了会话载体Cookie/Header中的内容。配置方式该过滤器通过 HTTP Connection Manager 下的 HTTP 过滤器链装配必须使用类型 URLtype.googleapis.com/envoy.extensions.filters.http.stateful_session.v3.StatefulSession对应的完整 proto 定义为 stateful_session.proto核心配置字段如下字段类型默认值说明session_stateconfig.core.v3.TypedExtensionConfig必填语义上最核心指定会话状态实现用于存取分配给会话的上游主机地址strictboolfalse是否严格路由到请求的目标主机。true时若目标不存在则按status_on_strict_destination_not_found返回若目标存在但不健康则始终返回503。false时回退到普通负载均衡stat_prefixstring空可选统计前缀为空则不输出任何统计status_on_strict_destination_not_founduint32503严格模式下目标主机不在可用端点集合中时返回的 HTTP 状态码strict为false时该字段被忽略设为0或不设置时取默认503此外还提供StatefulSessionPerRoute用于路由级覆盖见 stateful_session.proto它通过oneof override支持两种形式disabled在特定 vhost 或 route 上显式禁用该过滤器多个 per-filter-config 同时存在时取最具体的配置stateful_session为路由提供一份独立的StatefulSession配置可通过 RDS 下发。工作原理会话状态扩展点该过滤器最关键的配置项是session_state这个可扩展会话状态Extensible Session State。处理请求时过滤器会基于请求检索对应的会话及其上游主机检索结果将影响最终的负载均衡结果若未找到既有会话则创建会话用于存储选中的上游主机。需要强调的是这里的会话是抽象概念具体的存储细节完全取决于会话状态实现例如存在 Cookie 里还是存在响应 Header 里。结合 stateful_session.cc 的源码可梳理出完整的请求/响应处理链路请求阶段decodeHeaders解析出最具体的 per-route 配置若路由级禁用则直接Continue通过session_state中指定的工厂创建会话状态实例若会话中解析出上游地址upstreamAddress()有值则调用setUpstreamOverrideHost注入覆盖主机、strict 开关与严格模式失败状态码。响应阶段encodeHeaders若请求阶段没有会话状态且过滤器处于激活状态未被 per-route 禁用、请求已到达上游则累加no_session统计若有会话状态且拿到了最终上游主机则调用会话状态的onUpdate(host_address, headers)——若最终主机与会话记录不一致说明覆盖失败发生了回退则根据 strict 模式标记failed_open或failed_closed若一致则标记routed。会话状态是通过扩展工厂SessionStateFactory按session_state.name动态查找并实例化的具体机制在 stateful_session.cc。若配置中完全未指定session_state则会使用EmptySessionStateFactory返回空会话此时过滤器不产生任何粘性行为见 stateful_session.cc。官方示例Cookie 型会话状态目前官方支持三类会话状态扩展其中文档详细讲解的是Cookie 型envoy.http.stateful_session.cookie与Header 型envoy.http.stateful_session.header。以下为文档内嵌的 Cookie 型完整示例原样取自 stateful-cookie-session.yamlstatic_resources: listeners: - name: listener_0 address: socket_address: address: 0.0.0.0 port_value: 10000 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: type: type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http access_log: - name: envoy.access_loggers.stdout typed_config: type: type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog route_config: name: local_route virtual_hosts: - name: local_service domains: [*] routes: - match: prefix: / route: cluster: service1 http_filters: - name: envoy.filters.http.stateful_session typed_config: type: type.googleapis.com/envoy.extensions.filters.http.stateful_session.v3.StatefulSession session_state: name: envoy.http.stateful_session.cookie typed_config: type: type.googleapis.com/envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState cookie: name: global-session-cookie path: /path ttl: 120s - name: envoy.filters.http.router typed_config: type: type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: service1 load_assignment: cluster_name: service1 endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 8080该配置的行为Cookie 型会话状态从名为global-session-cookie的 Cookie 中解析当前会话应覆盖的上游主机若该主机确实存在于上游集群中请求将被路由到该主机。若请求没有有效 Cookie则负载均衡器正常挑选一个新上游主机并在响应阶段把选中的上游主机地址写入名为global-session-cookie的 Cookie通过Set-Cookie响应头。Cookie 值格式与生命周期细节从 cookie.proto 可以看到Cookie 型扩展把负载均衡器选中的上游地址编码进Set-Cookie响应头收到新请求时按 Cookie 名解析上游地址若地址对应有效上游主机则优先选择。其编码形式为 Base64文档示例中sticky-hostMS4yLjMuNDo4MA即1.2.3.4:80的 Base64 表示。需要说明的是根据 cookie.cc 的当前实现写入 Cookie 的内容实际是将上游地址连同可选的过期时间expires序列化后的消息再做 Base64 编码并且仅在最终选择的主机与会话记录不一致或原会话不存在时才更新 Cookie。stateful_session_filter.rst 中演示的cookie字段支持nameCookie 名示例为global-session-cookie源码 cookie.cc 会校验其非空否则抛异常pathCookie 的路径属性示例为/path同时它还被用作请求路径匹配器空路径或/匹配所有请求以/结尾的路径前缀匹配否则要求请求路径与 Cookie 路径相同或紧随其后是/、?、#之一见 cookie.ccttlCookie 有效期示例为120s源码中ttl为 0 时不写入expires会话永不过期见 cookie.cc此外还支持attributes附加 Cookie 属性。官方示例Header 型会话状态Header 型扩展的配置同样内嵌于文档原样取自 stateful-header-session.yamlstatic_resources: listeners: - name: listener_0 address: socket_address: address: 0.0.0.0 port_value: 10000 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: type: type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http access_log: - name: envoy.access_loggers.stdout typed_config: type: type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog route_config: name: local_route virtual_hosts: - name: local_service domains: [*] routes: - match: prefix: / route: cluster: service1 http_filters: - name: envoy.filters.http.stateful_session typed_config: type: type.googleapis.com/envoy.extensions.filters.http.stateful_session.v3.StatefulSession session_state: name: envoy.http.stateful_session.header typed_config: type: type.googleapis.com/envoy.extensions.http.stateful_session.header.v3.HeaderBasedSessionState name: session-header - name: envoy.filters.http.router typed_config: type: type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: service1 load_assignment: cluster_name: service1 endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 8080Header 型配置仅需一个字段name示例为session-header用于从下游请求中读取会话值、并在响应中生成同名响应头。其 proto 定义见 header.proto请求中若携带形如session-header: MS4yLjMuNDo4MA即1.2.3.4:80的 Base64的头部Envoy 会优先选择1.2.3.4:80作为上游处理上游响应时若最终选择的主机与会话记录不一致则把新选中主机地址 Base64 编码后写回session-header响应头见 header.cc。源码同样会校验name非空header.cc。使用 Header 型实现时需要注意两点原文档note原文Header 型实现假定客户端会使用最后一次提供的会话头值并在后续每个请求中携带它若需要基于路径匹配来启用/禁用粘性应使用StatefulSessionPerRoute进行路由级配置。扩展生态Envelope 型会话状态除文档主讲的 Cookie/Header 两种外仓库还提供了第三种官方扩展——Envelope 型envoy.http.stateful_session.envelope见 envelope.proto。它适用于会话上下文由上游服务器初始化的场景上游在会话首个响应中生成会话上下文如会话 ID 头或 Cookie客户端在后续请求中原样携带。其处理逻辑为处理上游响应时若响应中包含会话上下文无论新旧Envoy 会把该上下文与当前上游主机拼接成新的会话上下文处理下游请求时若请求包含会话上下文则从中剥离出上游主机。Header 模式下编码格式形如session-header: MS4yLjMuNDo4MAo;UV:eHh4eHh4Cg # base64(1.2.3.4:80);UV:base64(xxxxxx)其中UVupstream value段用于保存上游原始头值Envoy 据此把上游地址与会话值解耦回程时用UV段还原原始请求头。统计指标Statistics该过滤器在http.stat_prefix.stateful_session.命名空间下输出统计其中第一个stat_prefix来自所属 HTTP Connection Manager 的stat_prefix配置。注意两条关键规则原文档note过滤器自身未配置stat_prefix时不输出任何统计若配置了过滤器级stat_prefix会在stateful_session之后追加一段以区分多个实例例如http.stat_prefix.stateful_session.my_prefix.routed源码中统计前缀拼接逻辑见 stateful_session.ccper-route 配置覆盖不支持统计——即使在 per-route 的StatefulSession中设置了stat_prefix也不会输出统计对应实现见 stateful_session.ccper-route 配置传入空前缀。支持的统计指标定义于 stateful_session.h汇总如下名称类型说明routedCounter尝试了会话覆盖且成功应用、最终选中的上游与会话请求目标一致的请求总数failed_openCounter尝试覆盖但目标不可用、随后按默认负载均衡继续处理strict为false的请求总数failed_closedCounter尝试覆盖但目标不可用、以503关闭请求strict为true的请求总数no_sessionCounter过滤器激活但请求到达上游时没有会话状态的请求总数包括无会话 Cookie/Header 或会话提取失败的情况不包含过滤器在 per-route 被显式禁用的请求小结与实践建议Stateful Session 过滤器把粘性从负载均衡算法中彻底解耦出来哈希负载均衡的弱粘性依赖主机集合的稳定性而本过滤器通过session_state扩展在请求中显式携带目标上游主机实现了覆盖优先级高于负载均衡的强粘性。实践时的关键决策点包括会话载体选择Cookie 型适合浏览器类客户端自动携带、TTL 可控、支持路径匹配Header 型适合 API/微服务间调用需客户端配合回传头值Envelope 型适合上游已自带会话上下文的场景。strict 模式取舍追求粘性可靠性可开启strict目标不可达时 fail-closed 返回503追求可用性则保持falsefallback 到负载均衡但会积累failed_open统计。监控与安全务必为过滤器配置stat_prefix以获得routed/failed_open/failed_closed/no_session四类指标同时牢记文档警告——该特性可能造成上游负载不均、并允许外部控制请求目标需结合网络隔离与信任边界审慎启用。如需深入验证上述行为可直接查阅本文引用的 proto 定义、示例配置与源码文件并参考仓库中的实现与测试代码进行二次确认。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考