两个库存 Pod 都健康,为何一个更忙

先区分问的是外部请求数、代理选择次数、上游新连接数,还是库存实际处理次数。第 10 篇的 50/50 权重是路由目标,不能从 10 次样本推断每台必处理 5 次。即使 v1/v2 都在候选列表,长连接、HTTP/2 复用、端点权重、请求耗时、健康状态和 locality 优先级都会改变计数;有重试时一次用户请求可能对应多次后端尝试。

客户端连接、Service 后端选择与 Envoy cluster 选择分别作用于不同连接/请求单位

对于请求从 orders 到 inventory 的路径,可能先经过 Kubernetes Service 的连接级目标选择,再经过网格代理的 cluster 选址,具体取决于实际透明接管及协议模式。不能把某一个实现的“轮询”机械地套用到每个 HTTP 请求:先拿到相关 listener/route/cluster 的活跃配置及连接/请求日志,再确定正在讨论哪一层的选址。

选择时刻决定了统计含义

客户端只维持一条被 Service 转发到旧 Pod 的 TCP 连接时,后续复用该连接的请求可能持续命中旧实例;扩容引入新实例主要影响后续新建连接。Envoy 对其上游 cluster 的具体负载均衡与连接池调度另有策略,可能按请求选择可用 host,也可能受优先级、权重与健康集合约束;不能仅凭应用连接的长期后端不变,反推 Envoy 的负载均衡算法。

在 HTTP/2 中,一个 TCP 连接可同时承载多个流,不等于一个请求对应一条独立连接;逐条记录 downstream connection、upstream host、请求 ID 和库存版本,才能区分“连接固定后端”与“代理对请求逐次选 host”。并发不同步时,先完成的请求并不一定代表先分配的请求;将最终响应顺序当作选址顺序会产生误判。

健康和局部性还会改变候选集合:EndpointSlice readiness、Envoy 主动健康检查、被动异常摘除、locality 规则和 failover 是不同机制,具体是否启用要读取发布版本与活跃配置。把不健康 v2 排除后,仍宣称“请求必须平均分到 v1/v2”没有意义;如果两个故障域的实例配置了非对称权重,简单计数也不能反推故障。

两种连接模式的对照

在隔离实验集群按同一合成 SKU、并发数、请求 ID 与服务版本进行两组对照:第一组让客户端复用少量长连接,第二组显式新建连接;记录每条连接与每次请求、Envoy 的上游 host、应用版本响应。再仅对实验中的一个库存实例调低 readiness 或改变 locality,保存 EndpointSlice 与相关代理 cluster 当前健康/优先级配置,对比新旧连接的可用性。失败断言若“实际不可用实例仍持续收到预期应被摘除的新请求”必须非零;健康变化的传播时延不能在没跑前填一个数字。

前置环境检查(在 examples/service-mesh/ 执行):

1
SM_CONTEXT=service-mesh-lab SM_NAMESPACE=service-mesh-lab bash scripts/check-02.sh

此命令只读取资源,不是完整负载均衡实验。当前 examples/service-mesh/evidence/02/20261001T130351Z-2539112/ 中 kubectl 不存在、退出 127;第 03 篇 Envoy 下载也未完成。本篇所有真实代理 LB、健康与局部性观察 NOT_RUN,无性能数字。第 00 篇进程返回哪个版本只证明自身直连输入,与这里的双端点代理选择无关。

练习与参考解答

  1. 两个 endpoint 均列在快照里,一分钟内应用日志却是 v1:900、v2:100。是否证明权重写成了 90:10?参考解答:不能。先核对快照时间、健康和优先级、真实活跃权重、客户端连接复用与请求数,以及重试/失败的统计分母;应用处理次数不等于代理初次选 host 次数。时间窗口不同还可能产生错位。
  2. 不改权重,只把一个库存 Pod 标为 not ready,怎样构造能证伪“旧连接立即迁移”的实验?参考解答:在只针对合成实例的隔离集群保留到该 Pod 的旧连接,并开一批新连接;逐请求保存客户端 socket、EndpointSlice 条件、代理 endpoint 状态与后端 ID。若旧连接仍完成在途处理而新连接避开该实例,就能否定“端点变化必立即迁移所有连接”;实际结果需运行后填写。

官方资料与系列导航

系列导航:00 基线 → 10 版本与请求属性 → 11 负载均衡与连接复用(本文)→ 12 Gateway API 网格路由。