资讯动态

gRPC Stateful Session Filter 深入解析:基于 Cookie 的 xDS 有状态会话亲和性实现

发布时间:2026/9/10 18:01:51 来源:尧图企业网站定制
gRPC Stateful Session Filter 深入解析基于 Cookie 的 xDS 有状态会话亲和性实现【免费下载链接】grpcC based gRPC (C, Python, Ruby, Objective-C, PHP, C#)项目地址: https://gitcode.com/GitHub_Trending/gr/grpc有状态会话亲和性Stateful Session Affinity是负载均衡场景下的关键需求对于使用内存缓存、本地状态等资源的后端服务客户端必须持续访问同一后端端点。本文以 gRPC 仓库中src/core/ext/filters/stateful_session/目录为核心深入剖析StatefulSessionFilter通道过滤器如何通过 Cookie 实现会话绑定如何与xds_override_host负载均衡策略协同工作以及 xDS 如何动态下发其配置。读完本文你将理解这一机制的完整数据流、Cookie 编解码格式、关键配置项并能定位到对应的源码与测试进行深入验证。一、解决的问题无状态负载均衡下的会话粘滞需求默认情况下gRPC 客户端负载均衡如 round_robin会在多个可用后端之间分发请求同一客户端的连续 RPC 可能落在不同后端上。对于无状态服务这没有问题但一旦后端依赖内存缓存或本地有状态资源请求漂移就会导致缓存命中率下降甚至数据不一致。StatefulSessionFilter正是为这类场景设计的客户端侧过滤器。根据 AGENTS.md 的定位描述它提供一种将请求路由到处理过同一客户端先前请求的同一后端端点的机制并且被明确视为 gRPC 负载均衡能力栈中的重要组件。它不属于某一门语言C/Python/Ruby 等而是实现在 gRPC Core 层的通用通道过滤器所有语言绑定共享这一行为。二、整体架构两个核心类与一条协作链路该过滤器所在的目录结构非常精简只有三个文件src/core/ext/filters/stateful_session/ ├── AGENTS.md # 组件定位说明 ├── stateful_session_filter.h # StatefulSessionFilter 与 XdsOverrideHostAttribute 定义 └── stateful_session_filter.cc # 过滤器实现从 stateful_session_filter.h 可以看到两个核心类grpc_core::StatefulSessionFilter通道过滤器channel filter实现。它继承自ImplementChannelFilterStatefulSessionFilter通过MakePromiseBasedFilterStatefulSessionFilter, FilterEndpoint::kClient, kFilterExaminesServerInitialMetadata()注册为客户端端点过滤器见 stateful_session_filter.cc且需要检查服务端初始元数据以回写 Cookie。grpc_core::XdsOverrideHostAttribute一个调用属性call attribute派生自ServiceConfigCallData::CallAttributeInterface承担过滤器与xds_override_hostLB 策略之间的传话筒角色。协作链路分为两步请求方向StatefulSessionFilter从请求元数据的cookie头解析出地址列表写入XdsOverrideHostAttribute::cookie_address_list_LB 决策xds_override_host策略的 Picker 读取该属性按地址列表挑选后端并把实际选中地址列表写回XdsOverrideHostAttribute::actual_address_list_见 xds_override_host.cc响应方向StatefulSessionFilter拿到实际地址列表后若与 Cookie 中的地址不一致则通过set-cookie头回写更新后的 Cookie。这一过滤器提取 → LB 决策 → 过滤器回写的闭环正是整个会话亲和性机制的精髓。三、过滤器配置cookie_name / path / ttl 三要素过滤器配置由StatefulSessionFilter::Config结构定义见 stateful_session_filter.h共三个字段字段类型含义cookie_namestd::stringCookie 名称用于在请求头中定位会话 Cookie必填pathstd::stringCookie 的Path属性同时作为请求路径匹配范围可选空表示匹配所有路径ttlDurationCookie 有效期对应Max-Age属性可选Duration::Zero()表示不设置从 stateful_session_filter.cc 的实现看过滤器在客户端初始元数据阶段先做两个检查cookie_name为空或请求路径不匹配path时直接跳过本次过滤。路径匹配遵循 RFC 6265 §5.1.4未配置path时所有路径都匹配配置后要求 Cookie-path 是 request-path 的前缀且满足以下任一条件两者完全相同Cookie-path 以/结尾或 request-path 中未被 Cookie-path 覆盖的首字符是/。四、xDS 动态配置下发从 Envoy 协议到内部 Config该过滤器专为 xDS 设计可通过控制面在运行时动态下发配置。负责解析 xDS HTTP 过滤器配置的是 xds_http_stateful_session_filter.cc。它识别的 xDS 协议消息包括见 ConfigProtoName/OverrideConfigProtoNameenvoy.extensions.filters.http.stateful_session.v3.StatefulSession顶层过滤器配置envoy.extensions.filters.http.stateful_session.v3.StatefulSessionPerRoute按路由覆盖配置envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionStatesession_state 的 typed_config即 Cookie 方案解析逻辑ParseStatefulSession与 Envoy 的StatefulSession过滤器模型保持一致session_state字段中的typed_config必须声明为CookieBasedSessionState类型否则报 unsupported session state type随后从其中的cookie消息提取三要素——name必填缺省会报 field not present、ttl可选Duration、path可选。对StatefulSessionPerRoute若disabled字段为 true 或未携带stateful_session配置则返回一个空 Config语义是按路由禁用过滤器见 ParseOverrideConfig。这意味着 xDS 控制面可以在不同路由上精细化地开启或关闭会话亲和性实现真正的运行时动态调整。五、Cookie 的编解码与处理流程5.1 Cookie 值格式会话状态被编码进 Cookie 值格式为Base64(地址列表;集群名)内部明文格式是host;cluster其中host部分实际是逗号分隔的候选地址列表由 LB 策略写入见下文。地址列表可含多个地址按优先级排列供 LB 策略逐个尝试。5.2 请求方向读取并设置覆盖属性OnClientInitialMetadata 的处理步骤解析 CookieGetCookieValue从cookie请求头中按; 切分键值对找到与cookie_name匹配的值并 Base64 解码GetCookieValue。解码失败或不存在则视为空。拆分 host 与 cluster按;最多拆一次得到地址列表与集群名。创建调用属性在 Arena 上分配XdsOverrideHostAttributecookie_address_list为地址列表并通过service_config_call_data-SetCallAttribute()挂到本次调用上供 LB Picker 读取。集群覆盖判断GetClusterToUseGetClusterToUse从XdsClusterAttribute读取路由选定的集群若 Cookie 中的集群存在于当前路由的可用集群集合XdsRouteStateAttribute::HasClusterForRoute中则优先使用 Cookie 中的集群否则回退到路由选定的集群并把cluster_changed_标记为 true。需要注意如果路由使用 cluster specifier 插件集群名不带cluster:前缀则无法使用集群覆盖返回空字符串。5.3 响应方向按需回写 set-cookieOnServerInitialMetadata 和 OnServerTrailingMetadata 负责回写。只有在以下条件成立时才需要更新 CookieMaybeUpdateServerInitialMetadataLB 实际选中的地址列表actual_address_list与 Cookie 中记录的地址列表不同或集群发生了变化cluster_changed_为 true。此时构造新的set-cookie头cookie_nameBase64(实际地址列表;实际集群); HttpOnly[; Pathpath][; Max-Agettl秒数]HttpOnly始终附加Path与Max-Age视配置而定。特别地若服务端返回的是 Trailers-Only 响应无初始元数据Cookie 会被写入 trailing metadata 而非 initial metadata。5.4 生命周期保障Cookie 中的字符串地址列表、集群名通过AllocateStringOnArenaAllocateStringOnArena在 Arena 上分配确保其生命周期覆盖整个调用——这正是调用属性跨越过滤器与 LB 策略两个组件传递时不会悬垂的关键设计。六、与 xds_override_host LB 策略的协作细节StatefulSessionFilter本身不决定后端选择真正按 Cookie 执行路由的是xds_override_host负载均衡策略实现在 xds_override_host.cc。6.1 Picker 的覆盖选择逻辑Picker::PickOverriddenHost 是核心拿到XdsOverrideHostAttribute中的cookie_address_list逗号分隔按顺序在subchannel_map_中查找每个地址对应的子通道条目READY直接选中把该条目记录的address_list写回actual_address_list返回完整 Pick 结果IDLE触发RequestConnection()并PickResult::Queue()等待连接完成CONNECTING同样排队等待有地址但无子通道异步创建子通道CreateSubchannelForAddress后排队子通道 EDS 健康状态不在override_host_status_set中如 DRAINING则跳过。若 Cookie 中的地址全部不可用则回退到子策略child policy的普通 Pick 结果并在拿到子通道后把其地址列表写入actual_address_listPicker::Pick保证过滤器总能拿到实际选中的地址用于回写 Cookie。6.2 子通道映射与空闲回收策略维护subchannel_map_地址 →SubchannelEntry每个条目保存 EDS 健康状态、地址列表、每端点参数、上次使用时间与连接状态。地址列表的构造方式是把该端点地址放在最前、其余端点拼接在后形成优先顺序。为避免 Cookie 指向的子通道在子策略释放后失效OnSubchannelWrapperOrphan会在空闲超时connection_idle_timeout内克隆子通道保持持有IdleTimer周期性清扫超时的空闲子通道最小间隔 5 秒见 xds_override_host.cc。七、源码级验证Trace 与端到端测试7.1 调试开关该过滤器提供独立的 Trace 标志。在 trace_flags.yaml 中定义stateful_session_filter: default: false description: Stateful session affinity.结合xds_override_host_lb标志见 xds_override_host.cc 中的GRPC_TRACE_LOG(xds_override_host_lb, ...)可以完整观测过滤器读取 Cookie → Picker 覆盖选择 → 回写 set-cookie的全过程。7.2 端到端测试仓库提供了完整的端到端验证xds_override_host_end2end_test.cc。测试中使用名为grpc_session_cookie的 Cookie见该文件中的kCookieName并实现了一个Cookie结构体用于解析服务端返回的set-cookie头、校验 Cookie 名/值/属性再将其作为后续请求的cookie请求头回传。测试通过反复发起请求、让不同后端返回各自的 Cookie验证客户端能粘在 Cookie 指定的后端上。此外xds_http_filters_test.cc 与 xds_override_host_test.cc 分别覆盖了 xDS 配置解析与 LB 覆盖选择的单元级行为可作为阅读实现的补充入口。八、适用前提与限制依赖 xDS该过滤器通过XdsHttpStatefulSessionFilterFactory接入 xDS HTTP 过滤器链见 xds_http_stateful_session_filter.cc配置由控制面动态下发使用前提是启用 xDS 客户端如 gRPC xDS bootstrap必须配合xds_override_hostLB 策略过滤器只负责 Cookie 的读取与回写端点的实际选择完全依赖该 LB 策略同时集群覆盖仅在路由使用cluster:集群选择器时生效多 Cookie 值策略未定源码中留有 TODOFigure out the right behavior for multiple cookies当前实现取第一个匹配值见 GetCookieValueCookie 仅标记 HttpOnly 且不设 Secure 属性明文网络传输下请自行结合 TLS 等传输安全措施。通过本文梳理的请求读取 Cookie → 调用属性传递 → LB 覆盖选点 → 响应回写 Cookie闭环你可以清晰地把握 gRPC 有状态会话亲和性的实现全貌并以此为起点结合上文给出的源码路径与测试文件在真实 xDS 环境中验证或扩展这一机制。【免费下载链接】grpcC based gRPC (C, Python, Ruby, Objective-C, PHP, C#)项目地址: https://gitcode.com/GitHub_Trending/gr/grpc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

免费获取报价