微服务多了之后的治理难题
服务从 3 个拆到 30 个之后,每个服务之间都要互相调用。问题来了:限流怎么做?熔断写在哪?金丝雀发布的 5% 流量怎么切?调用链的耗时怎么统计?如果这些逻辑都写在每个业务服务的代码里,就是每个团队都要自己实现一遍,而且各写各的——A 服务的重试策略和 B 服务不一样,出了问题排查都对不上。
服务网格(Service Mesh)想解决的就是这件事:把这些「流量治理」的共性能力,从业务代码里彻底抽出来,交给一层专门的基础设施。业务代码只写业务逻辑,流量怎么路由、失败了怎么重试、要不要熔断,全部交给网格统一管。
业务代码写「我要调用订单服务」;服务网格决定「这次请求走哪条路、超时了怎么办、失败几次就熔断」。
- Sidecar每个服务旁边挂一个代理,所有进出流量都先过它。
- 流量治理路由、重试、熔断、限流全部在代理这层配置。
- 金丝雀按权重把一小部分流量切到新版本,观察没问题再放量。
- Istio这个领域最主流的开源实现。
服务网格:把治理能力抽出业务代码
在没有服务网格的时候,熔断、重试、限流这些事通常有两种做法:要么写在业务代码里(每个语言一套 SDK),要么靠入口那层负载均衡做一部分。前者的问题是每个团队都要实现一遍、版本还对不齐;后者的问题是它只管入口那一跳,服务和服务之间的内部调用它管不着。
服务网格换了个思路:在每个服务实例旁边都放一个专门的网络代理,这个服务的所有进出流量都先走代理,再由代理转发出去。治理规则(重试几次、超时多少、要不要熔断)全部配置在这些代理上——业务代码完全无感知,换语言、换框架都不影响,因为治理逻辑不在代码里。
Sidecar:每个服务配一个代理
这个「贴在服务旁边的代理」叫 Sidecar(边车)。在 Kubernetes 上用 Istio,就是给每个 Pod 自动注入一个额外的代理容器,和你的业务容器并排跑在同一个 Pod 里:
一个 Pod 里:
├── 你的业务容器(只写业务逻辑)
└── Istio Sidecar 代理(所有流量的必经之路)
服务 A 调服务 B 的实际路径:
业务A → Sidecar(A) → 网络 → Sidecar(B) → 业务B
正因为所有流量都被 Sidecar 截获,治理才变得可能:超时、重试、熔断、限流、链路追踪,全都在 Sidecar 这一层统一实现。业务代码调远程服务的那行代码一个字不用改,治理策略却可以随时调整。Istio 控制面再把你写的规则下发到每个 Sidecar,形成一张统一治理的网。
流量路由:金丝雀发布怎么配
服务网格最常用的能力之一,就是按权重切流量,实现金丝雀发布。规则用 YAML 声明:把 90% 流量给旧版本、10% 给新版本,观察新版本没问题再逐步放量:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
spec:
hosts:
- web
http:
- route:
- destination:
host: web
subset: stable
weight: 90
- destination:
host: web
subset: canary
weight: 10
这个配置一改,流量比例立刻生效,不需要改任何业务代码、也不需要重新部署。除了按权重,还能按请求特征分流:比如「带某个请求头的内部测试用户,全部导到新版本」——这比在业务代码里写灰度判断干净得多。配合上一篇讲的 GitOps,切流量这个动作本身也是一次 Git 评审。
熔断、超时与重试
上一篇高可用讲的熔断限流降级三件套,在服务网格里变成了统一配置。比如给某个下游依赖设个连接池熔断:连续失败到阈值,就直接短路、不再调用它:
连接池 / 熔断配置要点:
- 单次请求超时:别让慢请求一直挂着占资源
- 重试次数:设上限,避免故障时流量被重试放大
- 连续失败 N 次:熔断,直接快速失败
- 熔断后冷却一段时间:再放行少量试探
这里有两个新手最容易踩的坑:第一,重试一定要设上限。下游已经挂了,你的服务还在疯狂重试,等于把故障放大一倍。第二,超时要一层一层对齐——你给上游设了 3 秒超时,下游自己却要跑 5 秒,注定每次都超时。这些参数以前散落在每个服务的代码里,现在收到网格统一配,才真正对得齐。
可观测:网格天然带的数据
因为所有流量都经过 Sidecar,网格天然就拿到了全量的调用数据——哪个服务调哪个服务、每次耗时多少、成功率多少,不用业务代码埋点就有了。配合前面讲的全链路监控,服务之间的调用拓扑图、每跳的耗时分布,都是现成的。
这其实是服务网格一个常被低估的好处:可观测性从「每个服务各自埋点」变成「网格统一采集」。以前要推动每个团队接 trace SDK,漏了一个就断链;现在 Sidecar 在网络层就把调用关系记全了。治理和可观测,在这里是同一件事的两面。
什么时候才该上服务网格
讲了这么多好处,最后得泼盆冷水:服务网格不是银弹,它本身也带来复杂度——每个 Pod 多一个 Sidecar,吃内存、占 CPU、多一跳网络延迟,运维上也多了一套要照顾的组件。
| 阶段 | 该不该上服务网格 |
|---|---|
| 几个服务、小团队 | 别上,Service + 网关够用 |
| 十几个服务、多语言团队 | 再评估,重点看流量治理痛点 |
| 几十上百个服务、强治理需求 | 值得上,收益开始超过成本 |
一个务实的判断标准:如果你现在的痛点用 Nginx、K8s Service、应用里的 SDK 就能解决,就别急着上网格。当服务数量大到「每个团队各自实现重试熔断、版本还对不齐」真的变成了负担,金丝雀发布按权重切流量靠业务代码已经写不动了——那才是服务网格登场的时候。技术选型永远服务于问题本身,别为了「先进」而上。