服务网格 15:连接限制与异常实例摘除有什么区别
库存实例变慢,该拒绝请求还是换一台
同一批 orders → inventory 调用中,inventory-v1 响应变慢,而 inventory-v2 仍能处理请求。“连接数满了”与“v1 连续失败”需要两种不同的判断:前者保护某个代理指向上游集群的连接、排队请求或活跃请求等资源;后者依据目标实例的错误信号,暂时从该代理的健康负载均衡集合中摘除异常端点。把两者笼统叫作“熔断”,会让排障时把局部资源耗尽误判为实例不健康。
Envoy 的 circuit breaking 是分布式但不集中协调的代理限制:最大连接数、待处理请求、活跃请求、重试等分别计数,边界由各代理所见的 cluster、优先级及配置决定。达到待处理请求上限可能让新请求溢出,但不会据此断言整个服务的全局每秒请求数受到了精确限制。尤其是 HTTP/2 复用下,多请求不必对应多连接;连接阈值也不等于并发请求上限。实际连接数在实现与连接池边界下不宜写成严格永不越过设定值,需核对所用版本文档和代理计数器。
异常实例检测(outlier detection)是被动健康检查:根据代理观测到的连续错误、时间窗口成功率等信号,把某个上游端点从健康集合暂时摘除,并受最大摘除比例、时长及执行开关等配置约束。主动健康检查则定期探测目标,即使没有业务请求也可得到信号;两者可以组合,但不能说“给 v1 开个健康接口就等于已开启被动摘除”。如果只有一个可用实例,策略和门槛可能使错误继续暴露而不是神奇地换到 v2;恢复也应核对重新纳入的条件,不仅看客户端偶然一次 200。
把两个实验分开,才有可比较的结果
先用 examples/service-mesh/ 的无代理调用确认 inventory-v1、inventory-v2 和失败分支确实可区分:
1 | |
基线正常请求由 orders 指向 v1;-quote-delay 可在库存只读报价前引入人工延迟,错误端口则会导致应用无法连接。它们只说明服务处理速度或连接目标错误,没有 Envoy circuit breaker,也没有 outlier ejection;run-00.sh 启动 v2 不意味着代理正向它切换。不能把应用返回的 502/503 改写成代理溢出计数或实例被摘除。
待 Envoy 和隔离环境可用时需做两组正反对照。资源组:固定同一健康上游,先以低并发证明请求可达,再增加并发/排队请求,保存客户端非零结果、代理 upstream_cx_overflow 或相应 pending/request overflow 计数和后端实际请求数;降低负载后确认恢复。实例组:维持足够资源阈值,把 v1 的可控失败与 v2 的正常响应分别记录,核对代理的 ejection 事件/计数、当时可选端点和后续恢复;再关闭摘除做反例。主动健康检查须另存探测请求和状态,不能借用业务请求日志冒充。
应用故障桩的实测记录在 examples/service-mesh/evidence/verification/mainline-13-25/fault-rerun.log,退出码见同目录 fault-rerun.exit。它覆盖正常 200、应用 503、延迟 200 和 HTTP 响应前断连;只证明输入故障能够复现,两个代理组的资源限制与摘除实验仍 NOT_RUN。须等实际代理配置和请求记录齐备后再填写计数、错误来源与恢复时间。最终 200 也可能掩盖先前被重试的失败。
| 待验收组 | 正常基线 | 故障/过载客户端结果 | 代理计数或摘除事件 | 后端实际请求 |
|---|---|---|---|---|
| 资源溢出与降载 | 待运行 | 待运行 | 待运行 | 待运行 |
| v1 失败、v2 正常与恢复 | 待运行 | 待运行 | 待运行 | 待运行 |
| 关闭摘除的反例 | 待运行 | 待运行 | 待运行 | 待运行 |
用不同信号分别验证资源限制与摘除
以下命令在 examples/service-mesh 目录执行,使用 Kubernetes 1.33.4、Istio 1.27.0 的 sidecar 实验基线。先完成 04 的安装与累计应用部署;容器名为 app,Service 端口为 8080。先恢复上一章策略,再执行本章,避免超时、授权或出口规则互相污染。所有预期结果都是验收条件,未运行集群时保留 NOT_RUN。
1 | |
sm-probe 使用 orders ServiceAccount,明确注入 sidecar;它提供 curl,不依赖 scratch 应用镜像里不存在的 shell。每次请求同时保存客户端结果、来源代理配置和目标应用日志。
mainline/15/fault_server.py 是隔离的 Python 3.12.11 测试桩,支持 ok、fail、slow、reset;两个 Deployment 共用 fault-lab Service。MODE 环境变量让一个实例持续失败,查询参数可让单次请求变慢。它不替换累计库存应用,也没有真实库存副作用。
1 | |
outlier.yaml 允许摘除比例 100%,关闭 minHealthPercent 回退,并设置连续 2 次 5xx、基础摘除 10s;这是为了两实例实验能观察摘除,不是生产容量建议。先保存零故障计数,再要求失败实例出现 ejection 增量,后续请求偏向另一实例。Pod rollout 会换地址,因此这一步恢复证明新健康端点可用;要研究同一个端点到期重新纳入,需要保持 Pod 不变,用独立控制接口切换模式,本桩没有实现该接口,不能把 rollout 叫作自然恢复。
limits.yaml 替换同名 DestinationRule,移除 outlier,只限制本来源代理的连接、排队和活跃请求。并发组应出现 overflow 增量,串行恢复组应成功;只看到 503 而计数没变,资源限制验收不通过。清理时再删除 workloads.yaml 和 fault-code;23/25 要复用测试桩时可以保留,必须恢复 MODE=ok。
固定源码入口:Istio 1.27.0 pilot/pkg/networking/core/cluster_builder.go。该链接用于核对配置生成或执行机制;完整资源和命令保存在 examples/service-mesh/mainline/15/。静态检查通过不等于集群实验通过。
练习与参考解答
- 两个 sidecar 的连接限制各为 10,能断言整个库存服务同时最多 10 条连接吗?参考解答:不能。限制由各代理对目标 cluster 的连接池独立执行;有多个来源代理、连接复用和连接池差异时应分别读取各代理计数,不能把局部阈值当全局配额。
- v1 发生连续 503 后,v2 开始收到请求,能否直接认定是主动健康检查摘除了 v1?参考解答:不能。核对负载均衡池中 v1 的状态、outlier 摘除事件、主动探测日志和请求尝试;路由变更或客户端重试也可能改变最终看到的目标。关闭 outlier 后重试相同受控失败,是可证伪的对照。
官方参考与系列导航
- Envoy v1.37.0 circuit breaking:连接、待处理请求、活跃请求及重试限制的统计范围。
- Envoy v1.37.0 outlier detection:被动摘除与主动健康检查的区别。
系列导航:14 重试与副作用 → 15 连接限制与异常摘除(本文)→ 16 故障注入与镜像。
