服务网格 10:按版本和请求属性选择后端
“10% 给 v2”是路由意图,还是已发生的调用比例
同一服务链中的 inventory-v1、inventory-v2 返回各自版本标识;第 06 篇已拆开规则声明与代理执行。现在发布 v2:先让带 x-canary: yes 的合成请求稳定到 v2,再测试不带头时按权重选择 v1/v2。Subset 属于后端实例分类,匹配条件属于请求分类,权重属于某条 route 下的目标比例;三者不能写成一项配置。读者应能区分提交的权重、代理选择次数、后端处理次数与最终客户端成功次数。
图的第一步是请求匹配:若顺序靠前的规则匹配 canary 头,就不再按照后续默认权重规则选择;否则才进入默认路由。v1/v2 subset 必须与实际工作负载的版本标签一致,而不是只看 Deployment 名或镜像 tag。
路由规则、端点与观测单位
在 Istio 风格的配置中,DestinationRule 可给 inventory 定义 v1/v2 标签集合,VirtualService 可按 URI/请求头选目标及配置权重。只有当请求的 host、端口、header 落在相应 VirtualService 作用域内,且目标 subset 有实际可用 endpoint,代理才可能按意图执行;对象都存在不等于当前代理路由已切换。检查第 06–07 篇的资源提交、控制器处理、代理活跃 route/cluster/endpoint,再检查访问日志与库存应用的相同请求 ID。
权重不是“每十个请求必有一个 v2”。如果用独立同分布的简化模型,令选 v2 概率为 0.1,发送 20 次请求,则期望 v2 为 2 次,标准差为 sqrt(20 × 0.1 × 0.9) ≈ 1.34,恰好 0 次的概率为 0.9^20 ≈ 0.122。这些数是理论示意,不是本仓库压测结果,也不是对 Envoy 的具体实现保证。连接复用、负载均衡策略、重试、统计窗口和多个代理各自的采样都会改变可观察的计数。若代理对一个用户请求重试两次,后端看到的尝试数可能超过外部请求数,不能用两种分母计算同一个“灰度百分比”。
优先用显式头路由核对机制,再在固定采样数量、连接复用方式和无重试的条件下检验权重近似值。客户端应为每个用户请求生成不同 ID;后端日志、代理 attempt 记录、响应版本和账本要保持关联,防止读请求与将来的扣减请求混作同一安全场景。代理的权重选择不能保护非幂等写入的业务语义。
先验证确定路由,再统计权重
从 examples/service-mesh/ 运行 SM_CONTEXT=kind-service-mesh-sidecar bash scripts/cluster-case.sh 10。使用第 06 篇同一份 inventory-route.yaml:精确头 yes 到 v2、无头到 v1、错误 subset 失败、恢复标签后再到 v2。这四个判据先检验目标选择链,不能用一次随机样本代替。
权重扩展单独进行:确认没有其他同名实验规则后,应用原清单,再只替换默认规则的 route 数组。以下命令保持第一条 canary 匹配不变:
1 | |
每行成功响应带唯一 ID 和 inventory_version;统计 v2 行数除以成功行数,并另外保留失败退出码、请求总数 1000 与代理访问记录。若中途失败,loadgen 会退出,不能把剩余行仍称为 1000 请求成功样本。此处 reuse 控制的是 loadgen 到 frontend,orders 的连接池是另一段。
恢复确定路由用 kubectl --context kind-service-mesh-sidecar apply -f deploy/kubernetes/inventory-route.yaml,再次发送 canary 与无头请求。实验结束后删除本次创建的 VirtualService 和 DestinationRule,确保第 12 篇没有竞争规则。当前集群及权重采样均 NOT_RUN,没有预填 v2 百分比。
[PATTERN] 策略选择分为请求分类、版本分类、目标权重;分开修改可以定位到底是哪一维失效。
| 原则 | 检验点 |
|---|---|
| 确定性验证先行 | 头路由先确认两个版本可达 |
| 分母显式 | 请求、成功、尝试分别计数 |
| 统计不替代状态检查 | 活跃路由与样本一起保存 |
练习与参考解答
- 配置 10% 给 v2,20 次调用均到 v1,是否直接判断配置错误?参考解答:不能。按上述独立概率示意,0 次 v2 有约 12.2% 的概率;先核对实际规则、代理当前路由、样本是否经过该代理以及后端请求 ID,再增大样本量并固定连接和重试条件。真实代理算法与相关性还要单独检验。
- 保持请求头与权重不变,只把 v2 subset 标签改成 Pod 不具备的标签,会先在哪层暴露?参考解答:API 可能接受语法合法的规则,但对应代理的 cluster/endpoint 缺目标实例;也可能被特定实现提前诊断。必须保存对象状态、当前代理资源及带头请求的失败位置,不能猜一个固定 HTTP 码;若看到请求仍成功到 v2,应先查是否命中了另一条路由。
官方资料与系列导航
- Istio 流量迁移:版本分流的实践入口,当前环境未运行示例。
- VirtualService 与 DestinationRule:请求匹配、权重及 subset 声明;默认值待冻结版核对。
- Envoy v1.37.0 HTTP routing:route 与上游目标的执行边界。
系列导航:00 基线 → 09 协议与 TLS → 10 按版本和请求属性选择后端(本文)→ 11 负载均衡与连接复用。
