<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Microservices on 纪伟的个人博客</title><link>https://www.jiwei.space/tags/microservices/</link><description>Recent content in Microservices on 纪伟的个人博客</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Tue, 25 Nov 2025 10:00:00 +0800</lastBuildDate><atom:link href="https://www.jiwei.space/tags/microservices/index.xml" rel="self" type="application/rss+xml"/><item><title>服务网格：从 sidecar 到 Ambient，那笔"分布式税"怎么省</title><link>https://www.jiwei.space/posts/architecture/service-mesh/</link><pubDate>Tue, 25 Nov 2025 10:00:00 +0800</pubDate><guid>https://www.jiwei.space/posts/architecture/service-mesh/</guid><description>&lt;h2 id="写在前面"&gt;&lt;a href="#%e5%86%99%e5%9c%a8%e5%89%8d%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;写在前面
&lt;/h2&gt;&lt;p&gt;《每个程序员都该知道的延迟数字》里点过一笔账：Service Mesh 代理会增加延迟和资源消耗，但开销不是一个跨环境固定的“每跳毫秒数”。Istio 官方基准显示，它会随协议、连接数、请求率、负载大小、代理线程数和遥测功能明显变化。《后端架构实战（四）：微服务的&amp;quot;分布式税&amp;quot;》讲过这笔税为什么存在。&lt;/p&gt;
&lt;p&gt;这篇比较三种数据面路线：&lt;strong&gt;sidecar、Istio Ambient，以及以 eBPF 加速网络路径的 Cilium Service Mesh&lt;/strong&gt;。它们不是严格接替的“三代产品”，而是可以并存的架构选择。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;这篇是独立参考稿，不绑某个系列。它和《分布式税》《延迟数字》《Polly》《可观测性》几篇互相印证，串成&amp;quot;微服务通信&amp;quot;的一条线。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一服务网格到底解决什么"&gt;&lt;a href="#%e4%b8%80%e6%9c%8d%e5%8a%a1%e7%bd%91%e6%a0%bc%e5%88%b0%e5%ba%95%e8%a7%a3%e5%86%b3%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;一、服务网格到底解决什么
&lt;/h2&gt;&lt;p&gt;微服务一起来，每一条 service-to-service 链路都背着同一堆&lt;strong&gt;非功能性需求&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;安全&lt;/strong&gt;：双向加密 + 身份认证（mTLS）——别让内网裸奔；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;弹性&lt;/strong&gt;：超时、重试、熔断、限流——别让一个慢下游拖垮整条链路；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流量治理&lt;/strong&gt;：金丝雀发布、按比例分流、按 header 路由、流量镜像；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可观测&lt;/strong&gt;：服务间拓扑、延迟分布、错误率、访问日志。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每个服务自己用框架（.NET 的 Polly、Java 的 Resilience4j、Go 的中间件……）实现一遍 = &lt;strong&gt;语言不一致、版本不一致、改一条策略要动几十个仓库&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;服务网格做的事就一句话：&lt;strong&gt;把这一整层从应用代码里抽出来，下沉成独立的基础设施层&lt;/strong&gt;。应用只管业务逻辑，网格管&amp;quot;服务间通信的所有非功能性需求&amp;quot;。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;所以网格不是&amp;quot;替你交分布式税&amp;quot;，而是&lt;strong&gt;让交税的方式标准化、集中化&lt;/strong&gt;——税还在，但不再每个服务各交各的。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二第一代sidecaristio--envoy"&gt;&lt;a href="#%e4%ba%8c%e7%ac%ac%e4%b8%80%e4%bb%a3sidecaristio--envoy" class="header-anchor"&gt;&lt;/a&gt;二、第一代：Sidecar（Istio + Envoy）
&lt;/h2&gt;&lt;h3 id="怎么工作"&gt;&lt;a href="#%e6%80%8e%e4%b9%88%e5%b7%a5%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;怎么工作
&lt;/h3&gt;&lt;p&gt;每个 Pod 被 mutating webhook 注入一个 &lt;strong&gt;Envoy sidecar&lt;/strong&gt;，Pod 内所有进出流量被 iptables 规则重定向到本地 Envoy。应用完全无感——它以为自己直连对端，其实流量先被本地 Envoy 拦了一道。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Pod A Pod B
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┌────────────────┐ ┌────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ App │ │ App │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ │ │ ▲ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ▼ │ │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Envoy ───────┼──── mTLS ────→┼── Envoy │ ← 每 Pod 一个 sidecar
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└────────────────┘ └────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;一次调用: app → 本地 Envoy → 网络 → 对端 Envoy → 对端 app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 多了 2 个本地代理跳 + 2 次 mTLS 加解密
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="能力与代价"&gt;&lt;a href="#%e8%83%bd%e5%8a%9b%e4%b8%8e%e4%bb%a3%e4%bb%b7" class="header-anchor"&gt;&lt;/a&gt;能力与代价
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;能力&lt;/strong&gt;（这一代把网格能做的几乎全做到了）：mTLS + SPIFFE 身份、VirtualService 的金丝雀/分流/镜像、DestinationRule 的熔断/outlier detection、全量遥测（指标/链路/访问日志自动埋点）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代价&lt;/strong&gt;正是延迟篇那笔账：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;延迟&lt;/strong&gt;：请求多经过客户端和服务端代理，过滤器、遥测和排队都会增加平均与尾部延迟；实际值必须按自己的协议、并发和策略压测。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;资源&lt;/strong&gt;：每个工作负载都有代理。Istio 1.24 的官方参考测试中，1 KB 请求、1000 RPS、两个 worker 的单个 sidecar 约占 0.20 vCPU 和 60 MB 内存；这只是特定基准，不是容量规划常数。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;启动&lt;/strong&gt;：Pod 启动变慢且有序问题——应用先于 Envoy 就绪时，出站连接失败；Envoy 先于应用时，入站没人接。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;sidecar 模型的问题不在&amp;quot;能力不够&amp;quot;，而在&lt;strong&gt;粒度太细&lt;/strong&gt;：每个 Pod 都扛一个全功能 Envoy，绝大多数流量其实只用到它 mTLS 这一小块。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="三第二代ambientztunnel--waypoint"&gt;&lt;a href="#%e4%b8%89%e7%ac%ac%e4%ba%8c%e4%bb%a3ambientztunnel--waypoint" class="header-anchor"&gt;&lt;/a&gt;三、第二代：Ambient（ztunnel + waypoint）
&lt;/h2&gt;&lt;h3 id="核心思路l4-和-l7-解耦"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e6%80%9d%e8%b7%afl4-%e5%92%8c-l7-%e8%a7%a3%e8%80%a6" class="header-anchor"&gt;&lt;/a&gt;核心思路：L4 和 L7 解耦
&lt;/h3&gt;&lt;p&gt;Istio Ambient 的洞察是——&lt;strong&gt;大多数流量只需要 mTLS（L4），不该每个 Pod 扛一个全功能 Envoy&lt;/strong&gt;。于是把数据面拆成两层：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ztunnel&lt;/strong&gt;：每台 node 跑一个（DaemonSet），用 Rust 写的&lt;strong&gt;极轻 L4 代理&lt;/strong&gt;。只管 mTLS 加解密 + L4 授权。node 上所有 Pod 的流量统一由它过，传输用 &lt;strong&gt;HBONE&lt;/strong&gt;（HTTP/2 CONNECT 隧道协议）封装。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;waypoint&lt;/strong&gt;：&lt;strong&gt;按需&lt;/strong&gt;部署（per namespace 或 per service），本质还是 Envoy，但&lt;strong&gt;只在需要 L7 策略时才起&lt;/strong&gt;（流量分割、HTTP 级重试、L7 授权）。不需要 L7 的服务，流量只过 ztunnel，不碰 waypoint。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Node 1 Node 2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┌─────────────────────┐ ┌─────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Pod A Pod B │ │ Pod C Pod D │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ │ │ │ │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ▼ ▼ │ │ ▲ ▲ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └──→ ztunnel ────┼── HBONE ──┼→ ztunnel ←──┘ │ ← 每 node 一个(L4)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ (L4) │ 隧道 │ (L4) │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ │ │ │ (按需) │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ▼ │ │ ▼ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ waypoint │ │ waypoint │ ← 需要 L7 才起
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└─────────────────────┘ └─────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;L4 流量只过 ztunnel（轻）；要 L7 治理才加 waypoint 那一跳
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="收益与代价"&gt;&lt;a href="#%e6%94%b6%e7%9b%8a%e4%b8%8e%e4%bb%a3%e4%bb%b7" class="header-anchor"&gt;&lt;/a&gt;收益与代价
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;收益&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;减少重复资源&lt;/strong&gt;：从“每工作负载一个 Envoy”变成“每节点一个轻量 ztunnel + 按需 waypoint”；能省多少取决于 Pod、节点、waypoint 副本数和策略规模。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;避免 per-Pod 代理&lt;/strong&gt;：流量仍会经过源、目的节点上的 ztunnel，HBONE 也仍有代理、加密与排队成本；收益来自更轻的共享 L4 数据面，而不是“近乎零额外跳”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;零侵入&lt;/strong&gt;：业务 Pod 不再被注入 sidecar，迁移成本和故障面都小。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可并存&lt;/strong&gt;：Ambient 能和 sidecar 模式混跑，逐服务渐进迁移。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;代价&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;心智更绕&lt;/strong&gt;：ztunnel + waypoint + HBONE 三件事，比&amp;quot;一个 sidecar&amp;quot;复杂。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L7 那一跳省不掉&lt;/strong&gt;：要流量分割/重试，waypoint 本质还是个 Envoy——只是换了部署位置。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;能力仍在演进&lt;/strong&gt;：Ambient 于 2024 年 5 月随 Istio 1.22 进入 Beta，并于 2024 年 11 月随 1.24 达到 GA；核心 ztunnel、waypoint 和 API 已标记 Stable，但与 sidecar 的功能对齐仍是后续路线图的一部分。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="四另一条路线ebpfcilium-service-mesh"&gt;&lt;a href="#%e5%9b%9b%e5%8f%a6%e4%b8%80%e6%9d%a1%e8%b7%af%e7%ba%bfebpfcilium-service-mesh" class="header-anchor"&gt;&lt;/a&gt;四、另一条路线：eBPF（Cilium Service Mesh）
&lt;/h2&gt;&lt;h3 id="核心思路既然要离开应用进程干脆离开用户态"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e6%80%9d%e8%b7%af%e6%97%a2%e7%84%b6%e8%a6%81%e7%a6%bb%e5%bc%80%e5%ba%94%e7%94%a8%e8%bf%9b%e7%a8%8b%e5%b9%b2%e8%84%86%e7%a6%bb%e5%bc%80%e7%94%a8%e6%88%b7%e6%80%81" class="header-anchor"&gt;&lt;/a&gt;核心思路：既然要离开应用进程，干脆离开用户态
&lt;/h3&gt;&lt;p&gt;Cilium 使用 eBPF 在内核数据路径中完成服务负载均衡、网络策略和可观测等 L3/L4 工作；需要解析 HTTP、gRPC、Kafka 或 DNS 等应用层协议时，流量仍要重定向到用户态 Envoy。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;L3/L4&lt;/strong&gt;：eBPF 负责转发、负载均衡、策略执行和观测；可选的 WireGuard/IPsec 提供透明加密，但这不等同于成熟的工作负载级 mTLS 身份认证。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;身份认证&lt;/strong&gt;：Cilium 的 SPIFFE/SPIRE mutual authentication 在当前文档中仍为 Beta，若要同时获得加密，还需启用 WireGuard 或 IPsec。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L7&lt;/strong&gt;：eBPF 将需要应用层处理的流量透明重定向到 Envoy；具体部署形态取决于安装配置。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="一个必须说清的诚实点"&gt;&lt;a href="#%e4%b8%80%e4%b8%aa%e5%bf%85%e9%a1%bb%e8%af%b4%e6%b8%85%e7%9a%84%e8%af%9a%e5%ae%9e%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;一个必须说清的诚实点
&lt;/h3&gt;&lt;p&gt;Cilium 经常被宣传成&amp;quot;无 sidecar、eBPF 搞定一切&amp;quot;，但&lt;strong&gt;它的 L7 仍然要靠 Envoy&lt;/strong&gt;，只不过从&amp;quot;每 Pod 一个&amp;quot;换成了&amp;quot;每 node 一个共享实例&amp;quot;。所以：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Cilium 和 Ambient &lt;strong&gt;都不是“消灭所有代理”&lt;/strong&gt;。Ambient 用节点级 ztunnel 承担安全 L4 overlay，并按需加入 waypoint；Cilium 用 eBPF 承担大量 L3/L4 工作，但 L7 仍依赖 Envoy。二者的身份模型和策略 API 也不同。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="收益与代价-1"&gt;&lt;a href="#%e6%94%b6%e7%9b%8a%e4%b8%8e%e4%bb%a3%e4%bb%b7-1" class="header-anchor"&gt;&lt;/a&gt;收益与代价
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;收益&lt;/strong&gt;：L3/L4 极致性能（内核原生）、无 per-pod 开销、内核级可观测（网络指标天然丰富）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代价&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;L7 多租户隔离&lt;/strong&gt;是社区讨论点——共享 node Envoy 处理多服务流量，隔离不如 per-pod sidecar 干净。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;依赖满足 Cilium 支持矩阵的 Linux 内核与功能配置&lt;/strong&gt;；不要用一个笼统的 &lt;code&gt;5.10+&lt;/code&gt; 代替安装前的系统要求检查。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;控制面是 Cilium 自家体系&lt;/strong&gt;（&lt;code&gt;CiliumNetworkPolicy&lt;/code&gt; 等 CRD），和 Istio 的 &lt;code&gt;VirtualService&lt;/code&gt;/&lt;code&gt;DestinationRule&lt;/code&gt; 不通用，迁移有成本。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="五三条路线横评"&gt;&lt;a href="#%e4%ba%94%e4%b8%89%e6%9d%a1%e8%b7%af%e7%ba%bf%e6%a8%aa%e8%af%84" class="header-anchor"&gt;&lt;/a&gt;五、三条路线横评
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;维度&lt;/th&gt;
 &lt;th&gt;Sidecar（Istio 经典）&lt;/th&gt;
 &lt;th&gt;Ambient（Istio）&lt;/th&gt;
 &lt;th&gt;eBPF（Cilium）&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;数据面位置&lt;/td&gt;
 &lt;td&gt;每 Pod 一个 Envoy&lt;/td&gt;
 &lt;td&gt;每 node 一个 ztunnel + 按需 waypoint&lt;/td&gt;
 &lt;td&gt;内核 eBPF（L3/L4）+ 每 node Envoy（L7）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;L7 能力&lt;/td&gt;
 &lt;td&gt;全（Envoy 原生）&lt;/td&gt;
 &lt;td&gt;全（waypoint = Envoy）&lt;/td&gt;
 &lt;td&gt;有，但弱于 Istio 的体系&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;每 Pod 开销&lt;/td&gt;
 &lt;td&gt;大（几十~百 MB）&lt;/td&gt;
 &lt;td&gt;几乎为零（无 sidecar）&lt;/td&gt;
 &lt;td&gt;几乎为零（无 sidecar）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;延迟开销&lt;/td&gt;
 &lt;td&gt;多两个代理数据路径，需实测&lt;/td&gt;
 &lt;td&gt;L4 路径更轻；L7 增加 waypoint&lt;/td&gt;
 &lt;td&gt;L3/L4 主要在 eBPF 路径；L7 增加 Envoy&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;心智复杂度&lt;/td&gt;
 &lt;td&gt;中（最成熟、资料最多）&lt;/td&gt;
 &lt;td&gt;中高（ztunnel + waypoint + HBONE）&lt;/td&gt;
 &lt;td&gt;中（eBPF + 内核依赖）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;成熟度&lt;/td&gt;
 &lt;td&gt;最成熟&lt;/td&gt;
 &lt;td&gt;Istio 1.24 起 GA；功能仍持续对齐&lt;/td&gt;
 &lt;td&gt;Cilium 网络数据面成熟；mutual authentication 仍为 Beta&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;适用&lt;/td&gt;
 &lt;td&gt;已有 Istio、重度 L7 治理&lt;/td&gt;
 &lt;td&gt;新部署、求轻量、要 mTLS+可观测&lt;/td&gt;
 &lt;td&gt;新内核、追性能、L7 需求不重&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="六那笔税到底省了多少"&gt;&lt;a href="#%e5%85%ad%e9%82%a3%e7%ac%94%e7%a8%8e%e5%88%b0%e5%ba%95%e7%9c%81%e4%ba%86%e5%a4%9a%e5%b0%91" class="header-anchor"&gt;&lt;/a&gt;六、那笔税到底省了多少
&lt;/h2&gt;&lt;p&gt;回到延迟问题，更稳妥的比较方式是看数据路径，而不是套一个固定的“每 hop”数字：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sidecar（每工作负载 Envoy）：请求经过两端 Envoy，功能完整、资源隔离清晰
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Ambient L4（ztunnel + HBONE）：请求经过两端节点 ztunnel，共享轻量 L4 数据面
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cilium L3/L4（eBPF）：转发与策略主要在内核路径；需要 L7 时再进入 Envoy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;（Ambient/Cilium 的精确延迟要看各自的官方基准，随负载和场景漂移；这里给的是相对量级。）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;最该记住的洞察&lt;/strong&gt;：这些路线不是把分布式通信变成零成本，而是在代理隔离、共享资源和内核加速之间取舍。只要需要基于 HTTP 等应用层语义做治理，就需要 L7 解析；在本文讨论的实现里，这仍由 Envoy 承担。&lt;/p&gt;
&lt;p&gt;所以省下的是&lt;strong&gt;基础 mTLS 这一层的重复税&lt;/strong&gt;，不是&amp;quot;L7 治理本身的税&amp;quot;。L4 需求为主、L7 需求少的服务，是 Ambient/Cilium 最大的受益者。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="七怎么选决策清单"&gt;&lt;a href="#%e4%b8%83%e6%80%8e%e4%b9%88%e9%80%89%e5%86%b3%e7%ad%96%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;七、怎么选（决策清单）
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;□ 已有 Istio + 重度 L7 治理（金丝雀/重试都写在 VirtualService 里）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 留 sidecar；想降开销就逐服务迁 Ambient（能并存，渐进）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;□ 新部署、主要要 mTLS + 基础可观测、资源敏感
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → Ambient
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;□ Linux 内核满足目标 Cilium 版本的系统要求、重视网络数据面效率、团队熟悉 eBPF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → Cilium
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;□ 规模没到（几十个服务以下）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 可能根本不需要网格
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;最后一条最容易踩坑。网格自身的运维复杂度（控制面、版本升级、故障排查、CRD 体系）不低。规模没到时，可以按需求组合网络策略、平台提供的工作负载身份或 mTLS 能力、应用侧 Polly 与 OpenTelemetry；其中 Kubernetes NetworkPolicy 只做网络访问控制，本身不提供 mTLS。网格是规模问题的解药，不是小集群的补品。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="八和-net--aspnet-core-的分工"&gt;&lt;a href="#%e5%85%ab%e5%92%8c-net--aspnet-core-%e7%9a%84%e5%88%86%e5%b7%a5" class="header-anchor"&gt;&lt;/a&gt;八、和 .NET / ASP.NET Core 的分工
&lt;/h2&gt;&lt;p&gt;网格下沉之后，应用层还做什么？关键原则是&lt;strong&gt;别重叠&lt;/strong&gt;——两边都做同一件事，不仅浪费，还会出事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;mTLS&lt;/strong&gt;：若网格已覆盖这条链路，应用通常不必再重复建立一层同目的的传输加密；但端到端合规边界、网格外流量和应用层加密需求仍需单独评估。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;重试 / 超时 / 熔断&lt;/strong&gt;：&lt;strong&gt;二选一&lt;/strong&gt;。要么网格（Istio 的 &lt;code&gt;DestinationRule&lt;/code&gt; / Ambient waypoint），要么应用（&lt;strong&gt;Polly&lt;/strong&gt;）。&lt;strong&gt;两边都开 = 双重重试&lt;/strong&gt;，一个失败触发两层的重试风暴，放大流量、恶化雪崩——这是最常见的坑。一般原则：&lt;strong&gt;跨服务边界的通用策略 → 网格；和业务逻辑绑定的（&amp;ldquo;这个 API 失败重试 3 次且只对特定错误&amp;rdquo;)→ 应用层 Polly&lt;/strong&gt;。详见《Polly 的前世今生》《分布式税》。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可观测&lt;/strong&gt;：&lt;strong&gt;互补，不是替代&lt;/strong&gt;。网格给&amp;quot;服务间拓扑 + 调用延迟 + 错误率&amp;quot;（数据面自动埋点，零侵入）；OpenTelemetry 给&amp;quot;业务全链路 + 应用内 span&amp;quot;。两者通过 trace context 串联，画面才完整。详见《后端架构实战（七）：可观测性》。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流量治理&lt;/strong&gt;（金丝雀、AB、按 header 分流）：网格擅长，别在应用里自己造路由层。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;服务网格&lt;/strong&gt; = 把服务间通信的非功能性需求（mTLS / 弹性 / 治理 / 可观测）从应用下沉成独立基础设施层。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;三条路线&lt;/strong&gt;：sidecar（每工作负载 Envoy）、Ambient（节点级 ztunnel + 按需 waypoint）、Cilium（eBPF L3/L4 + 按需 Envoy L7）；它们并非严格代际替换。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;税省了什么&lt;/strong&gt;：Ambient 和 Cilium 都避免 per-Pod sidecar，但数据路径、身份认证与 L7 处理仍有成本；必须以目标环境的 p50/p99、吞吐和资源占用实测选型。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;选型&lt;/strong&gt;：看 L7 需求 / 规模 / 内核版本 / 团队能力；&lt;strong&gt;规模没到别硬上&lt;/strong&gt;，Polly + OTel 可能更划算。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;和应用层的边界&lt;/strong&gt;：mTLS 交网格、重试别两边都开（双重重试是最常见的坑）、可观测互补。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一句话：服务网格这十年的故事，就是&lt;strong&gt;把&amp;quot;分布式税&amp;quot;从每个应用进程里，一寸一寸挪到 node 和内核&lt;/strong&gt;——挪得越远，应用越轻，但那笔 L7 的核心税，到现在谁也没真消掉。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://istio.io/latest/blog/2024/ambient-reaches-beta/" target="_blank" rel="noopener"
 &gt;Istio Ambient 模式 Beta 公告（1.22，2024-05）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://istio.io/latest/blog/2024/ambient-reaches-ga/" target="_blank" rel="noopener"
 &gt;Istio Ambient 模式 GA 公告（1.24，2024-11）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://istio.io/latest/docs/ops/deployment/performance-and-scalability/" target="_blank" rel="noopener"
 &gt;Istio 性能与可扩展性基准（官方）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://istio.io/latest/docs/overview/dataplane-modes/" target="_blank" rel="noopener"
 &gt;Istio 数据面模式：Sidecar vs Ambient（官方文档）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cncf.io/blog/2024/08/23/ambient-mesh-can-sidecar-less-istio-make-your-application-faster/" target="_blank" rel="noopener"
 &gt;Ambient mesh 能让应用更快吗（CNCF Blog）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.infoq.com/articles/istio-ambient-mesh/" target="_blank" rel="noopener"
 &gt;Istio Ambient Mesh 深度解读（InfoQ）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cilium.io/use-cases/service-mesh/" target="_blank" rel="noopener"
 &gt;Cilium Service Mesh（官方）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.cilium.io/en/stable/network/servicemesh/" target="_blank" rel="noopener"
 &gt;Cilium Service Mesh 文档（官方）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.cilium.io/en/stable/network/servicemesh/mutual-authentication/mutual-authentication/" target="_blank" rel="noopener"
 &gt;Cilium Mutual Authentication 状态（官方）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Polly 的前世今生：从 Policy 到 ResiliencePipeline 的韧性范式重构</title><link>https://www.jiwei.space/posts/dotnet/polly-deep-dive/</link><pubDate>Sat, 15 Nov 2025 10:00:00 +0800</pubDate><guid>https://www.jiwei.space/posts/dotnet/polly-deep-dive/</guid><description>&lt;h2 id="写在前面"&gt;&lt;a href="#%e5%86%99%e5%9c%a8%e5%89%8d%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;写在前面
&lt;/h2&gt;&lt;p&gt;在分布式系统里，“调用失败”不是异常，而是常态。网络会抖、依赖会慢、对端会短暂挂掉。如果你的代码只会 &lt;code&gt;try/catch&lt;/code&gt; 然后把异常往上抛，那一次偶发的 503 就会变成一次真实的业务损失——订单失败、请求超时、用户体验坍塌。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Polly&lt;/strong&gt; 就是 .NET 生态用来回答这个问题的答案。它是事实标准的韧性（resilience）框架，把“重试、熔断、超时、降级、限流”这些原本散落各处的容错逻辑，抽象成可组合、可配置、可观测的策略积木。&lt;/p&gt;
&lt;p&gt;但 Polly 在 v8 做了一次近乎重写的范式升级：从“以 &lt;code&gt;Policy&lt;/code&gt; 为中心”迁到“以 &lt;code&gt;ResiliencePipeline&lt;/code&gt; 为中心”。这次重构不是换一套 API 那么简单，而是重新定义了“.NET 应用该如何做韧性工程”。这篇文章我们就把 Polly 的前世今生、七大策略、管线组合、可观测性，以及它背后的设计思想一次讲透。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;顺带：这篇和《HttpClient 的前世今生》是姊妹篇——HttpClient 负责“怎么把请求发出去”，Polly 负责“请求失败了怎么办”，两者在 .NET 8 通过 &lt;code&gt;Microsoft.Extensions.Http.Resilience&lt;/code&gt; 最终合流。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一为什么需要韧性故障是分布式系统的常态"&gt;&lt;a href="#%e4%b8%80%e4%b8%ba%e4%bb%80%e4%b9%88%e9%9c%80%e8%a6%81%e9%9f%a7%e6%80%a7%e6%95%85%e9%9a%9c%e6%98%af%e5%88%86%e5%b8%83%e5%bc%8f%e7%b3%bb%e7%bb%9f%e7%9a%84%e5%b8%b8%e6%80%81" class="header-anchor"&gt;&lt;/a&gt;一、为什么需要韧性：故障是分布式系统的常态
&lt;/h2&gt;&lt;p&gt;进入具体策略之前，先建立心智模型。分布式系统的故障大致分三类，&lt;strong&gt;每一类需要完全不同的对策&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;故障类型&lt;/th&gt;
 &lt;th&gt;典型场景&lt;/th&gt;
 &lt;th&gt;正确对策&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;瞬时故障&lt;/strong&gt; (transient)&lt;/td&gt;
 &lt;td&gt;网络抖动、短暂 5xx、限流 429&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;重试&lt;/strong&gt;——大概率自愈&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;持续故障&lt;/strong&gt; (sustained)&lt;/td&gt;
 &lt;td&gt;依赖真的挂了、磁盘满了&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;熔断&lt;/strong&gt;——停止徒劳重试，保护下游&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;自身过载&lt;/strong&gt; (overload)&lt;/td&gt;
 &lt;td&gt;自己被打爆、连接池耗尽&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;限流 / 舱壁&lt;/strong&gt;——主动收缩，保住容量&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;如果你对这三类故障用同一招（比如“一律重试三次”），就会在最坏情况下火上浇油：对端已经挂了你还猛重试，把下游彻底压垮，同时耗光自己的线程和连接。&lt;/p&gt;
&lt;p&gt;Polly 的价值正在于此：&lt;strong&gt;它把不同故障对应的策略做成可组合的积木，让你按需拼装&lt;/strong&gt;。理解了这一点，下面的 API 都是好理解的“积木说明书”。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;边界提示：本文讨论的所有策略都挂在&lt;strong&gt;调用方&lt;/strong&gt;一侧——HttpClient 对自己的&lt;strong&gt;出站调用&lt;/strong&gt;做保护，下游服务器并不知情。所以这是“我调别人时给自己加韧性”，与服务端的入站限流 / 降级是两套东西。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="二前世今生v7-到-v8-的范式重构"&gt;&lt;a href="#%e4%ba%8c%e5%89%8d%e4%b8%96%e4%bb%8a%e7%94%9fv7-%e5%88%b0-v8-%e7%9a%84%e8%8c%83%e5%bc%8f%e9%87%8d%e6%9e%84" class="header-anchor"&gt;&lt;/a&gt;二、前世今生：v7 到 v8 的范式重构
&lt;/h2&gt;&lt;p&gt;这是理解现代 Polly 最关键的一节。我们对比两段代码。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;v6/v7：以 &lt;code&gt;Policy&lt;/code&gt; 为中心。&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// v7：每个策略是一个 Policy 对象，手动 wrap 组合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Policy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpRequestException&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponseMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsSuccessStatusCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitAndRetryAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;breaker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Policy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpRequestException&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CircuitBreakerAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wrapped&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WrapAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;breaker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 手动组合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;wrapped&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ct&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它的特征与局限：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API 维度较多&lt;/strong&gt;：同步/异步、无结果/有结果分别使用不同接口和构造方式，组合时需要区分。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结果与异常用不同 API&lt;/strong&gt;：&lt;code&gt;.Handle&amp;lt;&amp;gt;()&lt;/code&gt; 管异常，&lt;code&gt;.OrResult(...)&lt;/code&gt; 管返回值，谓词表达割裂。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;手动 &lt;code&gt;PolicyWrap&lt;/code&gt; 组合&lt;/strong&gt;：顺序靠参数位置，缺乏统一的管线抽象。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;观测依赖手工回调&lt;/strong&gt;：v7 可以在重试、熔断等回调里记录日志，但缺少 v8 统一的 telemetry 管线。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配置与代码耦合&lt;/strong&gt;：阈值写死在代码里，改配置要重新发布。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;v8：以 &lt;code&gt;ResiliencePipeline&lt;/code&gt; 为中心。&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// v8：管线 + 策略 + 配置对象，结果与异常用统一谓词&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ResiliencePipelineBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponseMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;RetryStrategyOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponseMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;MaxRetryAttempts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Delay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BackoffType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DelayBackoffType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exponential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UseJitter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ShouldHandle&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;PredicateBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponseMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpRequestException&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsSuccessStatusCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddCircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;CircuitBreakerStrategyOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponseMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;FailureRatio&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;MinimumThroughput&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SamplingDuration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BreakDuration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ct&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;驱动这次重构的有四股力量：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;统一&lt;/strong&gt;：一个 &lt;code&gt;ResiliencePipeline&lt;/code&gt; 同时支持同步/异步、泛型化，策略即插即用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可观测&lt;/strong&gt;：内建 metrics（&lt;code&gt;Polly&lt;/code&gt; meter）与 telemetry，韧性第一次“看得见”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;集中配置&lt;/strong&gt;：options 对象 + 注册表让策略构造与业务调用解耦；校验和动态重载需要相应的 .NET options 集成。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;性能&lt;/strong&gt;：管线编译一次反复复用，大幅减少每次执行的分配。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以 v8 不是“换个写法”，而是&lt;strong&gt;把韧性从“手写策略”提升为“可运维的工程基础设施”&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="三核心心智strategy-与-pipeline"&gt;&lt;a href="#%e4%b8%89%e6%a0%b8%e5%bf%83%e5%bf%83%e6%99%bastrategy-%e4%b8%8e-pipeline" class="header-anchor"&gt;&lt;/a&gt;三、核心心智：Strategy 与 Pipeline
&lt;/h2&gt;&lt;p&gt;整个 v8 只有两个核心概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strategy（策略）&lt;/strong&gt;：单一韧性能力（重试、熔断、超时……），是管线的积木。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pipeline（管线）&lt;/strong&gt;：有序组合的策略链，外层策略包裹内层策略。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;执行模型是经典的“洋葱”，但比一句话更能帮助理解的是它的代码形态。每个策略本质是这样一个函数（伪代码）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Outcome&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResilienceContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Outcome&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ── 下行：调用内层前的准备 / 门禁（启动计时、看熔断状态）──&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 把控制权交给内层&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ── 上行：拿到结果后的决策（重试？记失败？抛超时？）──&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;next()&lt;/code&gt; 就是“内层那一段”：调用 &lt;code&gt;next&lt;/code&gt; = 控制权往内走，&lt;code&gt;next&lt;/code&gt; 返回 = 控制权往回走。整条管线是一摞这样的函数嵌套——&lt;strong&gt;下行做门禁、上行做决策&lt;/strong&gt;，真正的判断几乎都在拿到结果之后。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;顺手认出这个模式：它就是&lt;strong&gt;责任链（Chain of Responsibility）&lt;/strong&gt;——和《设计模式实战（六）》里讲过的 ASP.NET Core 中间件同源。严格说，Polly 是责任链的“装饰器链”变体：经典 GoF 责任链是“某个 handler 处理掉就结束”的单向链；这里是&lt;strong&gt;双向洋葱&lt;/strong&gt;，每个节点都参与（既预处理又后处理），请求一路下到真正的调用、结果再原路返回穿过所有节点。入站中间件、出站 &lt;code&gt;DelegatingHandler&lt;/code&gt;、Polly 管线——同一个模式的三次复用。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;以标准顺序 &lt;code&gt;TotalTimeout( Retry( CircuitBreaker( AttemptTimeout( Exec ) ) ) )&lt;/code&gt;（顺序的讲究见第五节）为例，看一次完整生命周期：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;下行（请求往里走） 上行（结果往外走）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;══════════════════ ══════════════════
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;① 总计时启动 ─┐ ┌─ 总计时释放
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;② 重试 第1次 ─┤ ├─ 重试：要不要再来一次？
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;③ 熔断 看状态(闭?) ─┤ ├─ 熔断：记一笔，要不要开路？
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;④ 单次计时启动 ─┤ ├─ 单次计时释放
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └→ Exec：真正发 HTTP ──────────────→ 结果原路返回 ─┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;两个最能帮你“看透”的认知：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;重试不是“从管顶重来”，而是 Retry 策略在上行阶段重新调用它的内层 &lt;code&gt;next&lt;/code&gt;&lt;/strong&gt;。所以&lt;strong&gt;总计时器跨所有重试持续在跑&lt;/strong&gt;（它在 Retry 外面，只启动一次），而&lt;strong&gt;单次计时器每次重试都重新建&lt;/strong&gt;（它在 Retry 里面）——这正是“总超时在外、单次超时在内”的运行时含义。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;熔断开路时，它在下行就短路&lt;/strong&gt;：状态为开时，熔断策略&lt;strong&gt;根本不调 &lt;code&gt;next&lt;/code&gt;&lt;/strong&gt;，直接返回失败——下游一个请求都收不到。这就是“保护下游”的运行时含义。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;v8 还在底层引入了一个关键抽象：&lt;strong&gt;&lt;code&gt;Outcome&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/strong&gt;——用“结果对象”统一表达“成功值 / 异常”。过去异常控制流和返回值检查是两条路，现在统一成一条：策略拿到的是 &lt;code&gt;Outcome&amp;lt;T&amp;gt;&lt;/code&gt;，用同一套 &lt;code&gt;ShouldHandle&lt;/code&gt; 谓词决定它算不算“需要处理的故障”。这是 v8 一切简洁性的根基。&lt;/p&gt;
&lt;h2 id="四七大韧性策略"&gt;&lt;a href="#%e5%9b%9b%e4%b8%83%e5%a4%a7%e9%9f%a7%e6%80%a7%e7%ad%96%e7%95%a5" class="header-anchor"&gt;&lt;/a&gt;四、七大韧性策略
&lt;/h2&gt;&lt;p&gt;这是 Polly 的核心武器库。其中重试、熔断、超时是“三大件”，必须吃透；其余四个按场景补充。&lt;/p&gt;
&lt;h3 id="41-重试retry对抗瞬时故障"&gt;&lt;a href="#41-%e9%87%8d%e8%af%95retry%e5%af%b9%e6%8a%97%e7%9e%ac%e6%97%b6%e6%95%85%e9%9a%9c" class="header-anchor"&gt;&lt;/a&gt;4.1 重试（Retry）——对抗瞬时故障
&lt;/h3&gt;&lt;p&gt;最常用，也最容易被滥用。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;退避（backoff）&lt;/strong&gt;：&lt;code&gt;Constant&lt;/code&gt; / &lt;code&gt;Linear&lt;/code&gt; / &lt;code&gt;Exponential&lt;/code&gt; 三种。绝对不要“立即重试”，否则瞬时故障下会形成同步重试风暴。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;必须加抖动（Jitter）&lt;/strong&gt;：&lt;code&gt;UseJitter = true&lt;/code&gt;。给每次退避叠加一个随机量，避免大量客户端在同一时刻集体重试（“惊群效应”）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;精确的谓词&lt;/strong&gt;：&lt;code&gt;ShouldHandle&lt;/code&gt; 决定“什么算可重试”。&lt;strong&gt;不是所有异常都该重试&lt;/strong&gt;——4xx 业务错误重试一百次结果也一样，只会浪费配额。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;必须有上限&lt;/strong&gt;：&lt;code&gt;MaxRetryAttempts&lt;/code&gt; 必须封顶，否则一次失败被放大成 N 倍流量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;幂等性&lt;/strong&gt;：重试 &lt;code&gt;GET&lt;/code&gt; 很安全；重试 &lt;code&gt;POST&lt;/code&gt; 必须带幂等键（Idempotency-Key），否则可能产生重复下单。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="42-熔断circuit-breaker在持续故障下保护下游"&gt;&lt;a href="#42-%e7%86%94%e6%96%adcircuit-breaker%e5%9c%a8%e6%8c%81%e7%bb%ad%e6%95%85%e9%9a%9c%e4%b8%8b%e4%bf%9d%e6%8a%a4%e4%b8%8b%e6%b8%b8" class="header-anchor"&gt;&lt;/a&gt;4.2 熔断（Circuit Breaker）——在持续故障下保护下游
&lt;/h3&gt;&lt;p&gt;当依赖真的挂了，重试只会火上浇油。熔断器的职责是&lt;strong&gt;主动停止调用，给下游喘息&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;三态循环：&lt;strong&gt;Closed（正常）→ Open（熔断，请求直接快速失败，不真正调用）→ Half-Open（试探性放行少量请求）→ 判定恢复则 Closed、否则重新 Open&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;v8 的熔断是&lt;strong&gt;高级实现&lt;/strong&gt;：它基于“采样窗口内的失败率”（&lt;code&gt;FailureRatio&lt;/code&gt; + &lt;code&gt;MinimumThroughput&lt;/code&gt; + &lt;code&gt;SamplingDuration&lt;/code&gt;），而不是简单的“连续失败 N 次”。这更贴近真实流量——偶尔一两次抖动不会误开熔断，但持续的失败率上升会被及时捕捉。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;作用域：熔断是“按下游聚合”的，不是单请求、也不是全 App 一个。&lt;/strong&gt; 这是最容易误解的地方：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;熔断器是&lt;strong&gt;有状态机&lt;/strong&gt;，状态挂在一条 &lt;code&gt;ResiliencePipeline&lt;/code&gt; 实例上，被“经过它的所有调用”&lt;strong&gt;共享&lt;/strong&gt;。失败率是&lt;strong&gt;跨请求聚合统计&lt;/strong&gt;的，不是每个请求自己单独算。&lt;/li&gt;
&lt;li&gt;但粒度是&lt;strong&gt;按下游 / 按 pipeline 隔离&lt;/strong&gt;：你给 &lt;code&gt;OrderApi&lt;/code&gt; 和 &lt;code&gt;InventoryApi&lt;/code&gt; 各配一套，各有各的熔断器，一个挂了不会误伤另一个。绝不该让全 App 共用一个 client/pipeline。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;单个请求的重试触发不了熔断&lt;/strong&gt;：虽然标准顺序下每次重试尝试都会被熔断器记一个采样，但开路有吞吐量门槛（&lt;code&gt;MinimumThroughput&lt;/code&gt;，标准默认要求窗口内至少约 100 次吞吐）+ 失败率门槛（约 10%）。一个请求的几次重试远凑不齐——要开路，得跨请求集体证明“这个下游不行了”。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;和重试对照着看，本质就清晰了：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;th&gt;重试（Retry）&lt;/th&gt;
 &lt;th&gt;熔断（Circuit Breaker）&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;状态&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;无状态&lt;/strong&gt;，每次调用自己循环&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;有状态&lt;/strong&gt;，跨请求共享&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;作用域&lt;/td&gt;
 &lt;td&gt;单次调用内部&lt;/td&gt;
 &lt;td&gt;整条 pipeline（按下游）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;判断依据&lt;/td&gt;
 &lt;td&gt;“这一次”失败 → 再来&lt;/td&gt;
 &lt;td&gt;“一段时间内多次调用”的失败率&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;重试是“单兵作战”，熔断是“全队观察”。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;哲学点：熔断不只是“保护下游不被打爆”，更是“给上游一个快速失败（fail-fast）”——与其让请求挂 30 秒超时，不如毫秒级返回失败，把容量留给其他能成功的请求。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="43-超时timeout给每次调用一个上限"&gt;&lt;a href="#43-%e8%b6%85%e6%97%b6timeout%e7%bb%99%e6%af%8f%e6%ac%a1%e8%b0%83%e7%94%a8%e4%b8%80%e4%b8%aa%e4%b8%8a%e9%99%90" class="header-anchor"&gt;&lt;/a&gt;4.3 超时（Timeout）——给每次调用一个上限
&lt;/h3&gt;&lt;p&gt;Polly v8 的 timeout strategy 通过取消令牌通知回调停止，并在超时时抛出 &lt;code&gt;TimeoutRejectedException&lt;/code&gt;。回调必须使用 Polly 传入的令牌并支持协作式取消；如果委托忽略令牌，底层工作可能在调用方收到超时后仍继续运行。旧版 Polly 的 optimistic/pessimistic 模式不应套到 v8 API 上。&lt;/p&gt;
&lt;p&gt;通常配两层：&lt;strong&gt;总超时&lt;/strong&gt;（包住整个重试过程）+ &lt;strong&gt;每次尝试超时&lt;/strong&gt;（包住单次调用）。两层都不可少。&lt;/p&gt;
&lt;h3 id="44-对冲hedging对抗尾延迟"&gt;&lt;a href="#44-%e5%af%b9%e5%86%b2hedging%e5%af%b9%e6%8a%97%e5%b0%be%e5%bb%b6%e8%bf%9f" class="header-anchor"&gt;&lt;/a&gt;4.4 对冲（Hedging）——对抗尾延迟
&lt;/h3&gt;&lt;p&gt;针对 p99 抖动：发出第一个请求，若在 &lt;code&gt;Delay&lt;/code&gt; 内没返回，就&lt;strong&gt;并行&lt;/strong&gt;再发一个，谁先回用谁。在 p99 严重的系统里（想想 Jeff Dean 那张“延迟尾部放大”图），对冲能把慢请求的尾部显著拉平。代价是多打流量，&lt;strong&gt;只适合幂等或廉价的调用&lt;/strong&gt;。它对应 HttpClient 侧的 &lt;code&gt;AddStandardHedgingHandler&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="45-限流rate-limiter控制自身或下游速率"&gt;&lt;a href="#45-%e9%99%90%e6%b5%81rate-limiter%e6%8e%a7%e5%88%b6%e8%87%aa%e8%ba%ab%e6%88%96%e4%b8%8b%e6%b8%b8%e9%80%9f%e7%8e%87" class="header-anchor"&gt;&lt;/a&gt;4.5 限流（Rate Limiter）——控制自身或下游速率
&lt;/h3&gt;&lt;p&gt;基于 &lt;code&gt;System.Threading.RateLimiting&lt;/code&gt; 的 limiter。客户端侧限流既可保护下游，也可避免自己过快消耗配额；具体是速率还是并发约束取决于所配置的 &lt;code&gt;RateLimiter&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="46-并发限制concurrency-limiter舱壁思路故障隔离与容量保护"&gt;&lt;a href="#46-%e5%b9%b6%e5%8f%91%e9%99%90%e5%88%b6concurrency-limiter%e8%88%b1%e5%a3%81%e6%80%9d%e8%b7%af%e6%95%85%e9%9a%9c%e9%9a%94%e7%a6%bb%e4%b8%8e%e5%ae%b9%e9%87%8f%e4%bf%9d%e6%8a%a4" class="header-anchor"&gt;&lt;/a&gt;4.6 并发限制（Concurrency Limiter，舱壁思路）——故障隔离与容量保护
&lt;/h3&gt;&lt;p&gt;限制&lt;strong&gt;并发执行数&lt;/strong&gt;，超出时快速拒绝而非排队堆积。它的核心价值是&lt;strong&gt;隔离&lt;/strong&gt;：把不同依赖放进不同“舱室”，一个慢依赖拖不垮整艘船——避免一个慢下游占满线程池/连接池，导致整个进程假死。&lt;/p&gt;
&lt;h3 id="47-降级fallback优雅失败"&gt;&lt;a href="#47-%e9%99%8d%e7%ba%a7fallback%e4%bc%98%e9%9b%85%e5%a4%b1%e8%b4%a5" class="header-anchor"&gt;&lt;/a&gt;4.7 降级（Fallback）——优雅失败
&lt;/h3&gt;&lt;p&gt;所有策略都兜不住时，返回一个默认值、缓存或兜底逻辑，让用户看到“降级但可用”的结果，而不是刺眼的 500。这是用户体验的最后一道防线。&lt;/p&gt;
&lt;h2 id="五组合管线顺序就是语义"&gt;&lt;a href="#%e4%ba%94%e7%bb%84%e5%90%88%e7%ae%a1%e7%ba%bf%e9%a1%ba%e5%ba%8f%e5%b0%b1%e6%98%af%e8%af%ad%e4%b9%89" class="header-anchor"&gt;&lt;/a&gt;五、组合：管线顺序就是语义
&lt;/h2&gt;&lt;p&gt;策略本身只是积木，&lt;strong&gt;怎么排列它们决定了语义&lt;/strong&gt;。这是 Polly 最容易被用错的地方。.NET 8 标准韧性管线给出的“出厂正确顺序”（由外到内）是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Rate / Concurrency Limiter ← 入口：先控制进入管线的并发
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Total Timeout ← 总超时：包住整个重试过程
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Retry ← 重试：处理瞬时故障
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Circuit Breaker ← 熔断：持续故障时让重试快速失败
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Attempt Timeout ← 内层：单次尝试的时限
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;你的业务调用
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;每一层的位置都有理由：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;限流/舱壁在最外&lt;/strong&gt;：在进入任何重试逻辑前先控制并发与速率，防止“重试放大流量”冲垮自己。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;总超时包住重试&lt;/strong&gt;：否则 3 次重试 × 每次挂 30 秒，一个请求能拖 90 秒。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;重试在熔断之外&lt;/strong&gt;：每次重试尝试都会经过熔断器；一旦熔断打开，重试会立刻拿到 fast-fail，不真正调用下游，而重试自身的失败计数仍能正常累计。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;每次尝试超时在最内&lt;/strong&gt;：它只约束单次调用，不约束整个重试链。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对冲变体（&lt;code&gt;AddStandardHedgingHandler&lt;/code&gt;）则把“重试 + 熔断 + 单次超时”整体塞进对冲策略的内部，外面包一层总超时。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;这个“顺序敏感的洋葱模型”，和 &lt;code&gt;DelegatingHandler&lt;/code&gt;、ASP.NET Core 中间件完全同构。&lt;strong&gt;理解了管线的语义，就理解了 .NET 一大类框架的设计语言。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="六配置驱动options-与-registry"&gt;&lt;a href="#%e5%85%ad%e9%85%8d%e7%bd%ae%e9%a9%b1%e5%8a%a8options-%e4%b8%8e-registry" class="header-anchor"&gt;&lt;/a&gt;六、配置驱动：Options 与 Registry
&lt;/h2&gt;&lt;p&gt;v8 支持通过 DI 集中注册命名管线。下面是集中配置示例；若要从配置文件绑定或动态重载，需要额外使用 options/配置集成，不能仅凭这段代码自动获得热更新：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 在 DI 中集中注册一条命名管线&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddResiliencePipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;order-api&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;RetryStrategyOptions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;MaxRetryAttempts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BackoffType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DelayBackoffType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exponential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UseJitter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddCircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;CircuitBreakerStrategyOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;FailureRatio&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0.5&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 取用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResiliencePipelineProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="n"&gt;DoAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetPipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;order-api&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;好处是阈值和管线构造集中管理、业务代码只按 key 取用。是否启动时校验、是否支持动态重载，取决于采用的 options 注册与 reload 机制。&lt;/p&gt;
&lt;h2 id="七可观测性v8-最大的飞跃"&gt;&lt;a href="#%e4%b8%83%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7v8-%e6%9c%80%e5%a4%a7%e7%9a%84%e9%a3%9e%e8%b7%83" class="header-anchor"&gt;&lt;/a&gt;七、可观测性：v8 最大的飞跃
&lt;/h2&gt;&lt;p&gt;Polly v8 会为管线与策略生成遥测事件；使用 &lt;code&gt;Microsoft.Extensions.Resilience&lt;/code&gt; 集成时，可通过日志和 &lt;code&gt;System.Diagnostics.Metrics&lt;/code&gt; 接入观测系统，并用 telemetry options 配置严重级别、监听器与标签。不存在一个适用于本文所有构建方式的通用 &lt;code&gt;.EnableTelemetry()&lt;/code&gt; 开关。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;重试了几次、每次因为什么失败；&lt;/li&gt;
&lt;li&gt;熔断器的状态切换（Closed → Open → Half-Open）；&lt;/li&gt;
&lt;li&gt;超时、限流、舱壁拒绝的计数。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些指标可以直接进 OpenTelemetry / Prometheus / Grafana 仪表盘。&lt;/p&gt;
&lt;p&gt;为什么这很重要？&lt;strong&gt;看不见的韧性是危险的。&lt;/strong&gt; 一个配错的熔断器可能静默地把一半流量快速失败，而你在告警里只看到“错误率升高”却无从定位。v8 把可观测性作为一等公民，让韧性&lt;strong&gt;可监控、可调优、可归因&lt;/strong&gt;——这是它从“库”升级为“基础设施”的标志。&lt;/p&gt;
&lt;h2 id="八与-httpclient-合流microsoftextensionshttpresilience"&gt;&lt;a href="#%e5%85%ab%e4%b8%8e-httpclient-%e5%90%88%e6%b5%81microsoftextensionshttpresilience" class="header-anchor"&gt;&lt;/a&gt;八、与 HttpClient 合流：Microsoft.Extensions.Http.Resilience
&lt;/h2&gt;&lt;p&gt;回到姊妹篇。.NET 8 的 &lt;code&gt;Microsoft.Extensions.Http.Resilience&lt;/code&gt; 是 Polly v8 与 &lt;code&gt;IHttpClientFactory&lt;/code&gt; 的官方桥梁：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHttpClient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderApi&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(...)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddStandardResilienceHandler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 限并发 + 总超时 + 重试 + 熔断 + 单次超时&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;AddStandardResilienceHandler&lt;/code&gt; / &lt;code&gt;AddStandardHedgingHandler&lt;/code&gt; 把预配置的 v8 管线接进 HttpClient 出站管线，但并不等于启用 Polly 的“全部策略”；fallback 等需求仍需自定义。官方还建议一个 client 只配置一个 resilience handler，避免无意叠加。&lt;/p&gt;
&lt;h2 id="九设计思想polly-教会了我们什么"&gt;&lt;a href="#%e4%b9%9d%e8%ae%be%e8%ae%a1%e6%80%9d%e6%83%b3polly-%e6%95%99%e4%bc%9a%e4%ba%86%e6%88%91%e4%bb%ac%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;九、设计思想：Polly 教会了我们什么
&lt;/h2&gt;&lt;p&gt;回头看，Polly 的演进浓缩了几个值得带走的思想：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;“故障是常态，韧性是工程义务”。&lt;/strong&gt; 在分布式系统里，容错不是可选优化，而是基本功。把重试/熔断当业务逻辑的一部分来设计，而不是事后补丁。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“策略即管线，组合优于硬编码”。&lt;/strong&gt; 和 HttpClient、ASP.NET Core 一脉相承——把横向关注点拆成可插拔的策略，按顺序组合，而不是在每个调用点重复 &lt;code&gt;try/catch&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“Outcomes over exceptions”。&lt;/strong&gt; v8 用 &lt;code&gt;Outcome&amp;lt;T&amp;gt;&lt;/code&gt; 统一表达成败，摆脱“用异常做控制流”的旧范式。这是更健康、更易组合的失败模型。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“可观测的韧性”。&lt;/strong&gt; 看不见就调不了。把可观测性内置进框架，让韧性从黑盒变成仪表盘上的一等指标。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“对下游负责”。&lt;/strong&gt; 熔断、限流、舱壁，本质都是“自我约束以保护整个系统”。一个有责任感的客户端，应当主动限制自己，而不是无限重试把下游压垮。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="十决策与避坑清单"&gt;&lt;a href="#%e5%8d%81%e5%86%b3%e7%ad%96%e4%b8%8e%e9%81%bf%e5%9d%91%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;十、决策与避坑清单
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;按故障选策略&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;你遇到的问题&lt;/th&gt;
 &lt;th&gt;用&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;偶发网络抖动 / 短暂 5xx&lt;/td&gt;
 &lt;td&gt;Retry + Jitter&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;依赖持续故障&lt;/td&gt;
 &lt;td&gt;Circuit Breaker&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;请求偶发慢 / p99 高&lt;/td&gt;
 &lt;td&gt;Hedging&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;自己被打爆 / 保护下游配额&lt;/td&gt;
 &lt;td&gt;Rate Limiter&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;一个慢依赖拖垮全盘&lt;/td&gt;
 &lt;td&gt;Bulkhead&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;想给用户兜底体验&lt;/td&gt;
 &lt;td&gt;Fallback&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;任何调用都必须有&lt;/td&gt;
 &lt;td&gt;Timeout&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;常见坑&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;重试风暴：无 jitter + 无退避，瞬时故障下集体同步重试。&lt;/li&gt;
&lt;li&gt;重试不可幂等的 &lt;code&gt;POST&lt;/code&gt; 不带幂等键 → 重复下单。&lt;/li&gt;
&lt;li&gt;有重试、有单次超时，却忘了总超时 → 单请求拖到天荒地老。&lt;/li&gt;
&lt;li&gt;熔断阈值设太敏感（正常抖动就开）或太迟钝（形同虚设）。&lt;/li&gt;
&lt;li&gt;把 4xx 业务错误当成“可重试故障”。&lt;/li&gt;
&lt;li&gt;韧性策略没开 telemetry，上线即黑盒，出事无从定位。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="结语"&gt;&lt;a href="#%e7%bb%93%e8%af%ad" class="header-anchor"&gt;&lt;/a&gt;结语
&lt;/h2&gt;&lt;p&gt;Polly 从一个“重试库”长成了“.NET 韧性工程的基础设施”。v8 的 &lt;code&gt;ResiliencePipeline&lt;/code&gt; 范式重构，让韧性&lt;strong&gt;统一、可配置、可观测&lt;/strong&gt;——这三点，恰恰是生产级分布式系统最需要的。&lt;/p&gt;
&lt;p&gt;当你下一次写出 &lt;code&gt;AddStandardResilienceHandler()&lt;/code&gt; 时，背后是一套经过千锤百炼的韧性工程语言：重试带抖动、熔断保护下游、超时封顶延迟、一切皆可观测。理解了这套语言，你写出的就不再是“能跑的代码”，而是“对下游负责、对自己克制、对故障坦然”的分布式客户端。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.pollydocs.org/strategies/" target="_blank" rel="noopener"
 &gt;Polly v8：Resilience strategies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.pollydocs.org/advanced/telemetry.html" target="_blank" rel="noopener"
 &gt;Polly v8：Telemetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/dotnet/core/resilience/" target="_blank" rel="noopener"
 &gt;.NET 韧性开发概览（Microsoft Learn）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/dotnet/core/resilience/http-resilience" target="_blank" rel="noopener"
 &gt;HTTP resilience 标准管线（Microsoft Learn）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>后端架构实战（八）：落地——用 ASP.NET Core 搭一个微服务骨架</title><link>https://www.jiwei.space/posts/architecture/microservices/08-aspnetcore-microservice/</link><pubDate>Tue, 08 Apr 2025 10:00:00 +0800</pubDate><guid>https://www.jiwei.space/posts/architecture/microservices/08-aspnetcore-microservice/</guid><description>&lt;h2 id="写在前面"&gt;&lt;a href="#%e5%86%99%e5%9c%a8%e5%89%8d%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;写在前面
&lt;/h2&gt;&lt;p&gt;前七篇全是道理：权衡、单体、拆分、分布式税、一致性、通信、可观测性。这一篇&lt;strong&gt;把理论落成代码&lt;/strong&gt;——用 ASP.NET Core 搭一个最小可用的微服务骨架。&lt;/p&gt;
&lt;p&gt;它不会是一个完整生产系统，但会覆盖微服务的&amp;quot;承重墙&amp;quot;：&lt;strong&gt;项目结构、依赖注入、API 网关、健康检查、弹性（Polly）、可观测性（OpenTelemetry）&lt;/strong&gt;。每一处都对应前面某一篇讲过的道理。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;前置：本篇假设你读过我的《ASP.NET Core 学习笔记》系列（中间件管道、DI、认证授权）。基于 &lt;strong&gt;.NET 8 LTS&lt;/strong&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一整体结构"&gt;&lt;a href="#%e4%b8%80%e6%95%b4%e4%bd%93%e7%bb%93%e6%9e%84" class="header-anchor"&gt;&lt;/a&gt;一、整体结构
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;一个最小微服务系统（4 个工程）：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Gateway/ API 网关（YARP，统一入口、路由、鉴权）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OrderService/ 订单服务（业务 A）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; InventoryService/ 库存服务（业务 A 的依赖）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Shared/ 少量稳定的传输契约（需独立版本化，避免共享领域模型）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 对应前文：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 拆分（第三篇）→ 按领域切 Order / Inventory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 通信（第六篇）→ 网关 + 服务间 HTTP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 分布式税（第四篇）→ 健康检查、Polly 弹性
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 可观测性（第七篇）→ OpenTelemetry 串联
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;工程依赖方向（单向，严禁循环）：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Gateway ──→ Shared
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OrderService ──→ Shared
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; InventoryService ──→ Shared
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OrderService ──调用──→ InventoryService（运行时 HTTP，非编译依赖）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 关键：服务间运行时依赖走网络，编译期互不引用
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 这样才能独立编译、独立部署。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="二每个服务的内部分层"&gt;&lt;a href="#%e4%ba%8c%e6%af%8f%e4%b8%aa%e6%9c%8d%e5%8a%a1%e7%9a%84%e5%86%85%e9%83%a8%e5%88%86%e5%b1%82" class="header-anchor"&gt;&lt;/a&gt;二、每个服务的内部分层
&lt;/h2&gt;&lt;p&gt;单个服务内部，按职责分层（不是按&amp;quot;被拆成服务&amp;quot;的技术层——区别于第三篇的反模式）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OrderService/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── OrderService.Api/ 表现层（Controller / 最小 API）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── 引用 Application、Domain
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── OrderService.Application/ 应用层（用例、编排、接口定义）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── 引用 Domain
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── OrderService.Domain/ 领域层（实体、领域服务、规则）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── 不依赖任何人（依赖倒置的核心）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── OrderService.Infrastructure/ 基础设施（DB、外部调用、实现）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 引用 Application（实现接口）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 依赖方向永远向内，Domain 在最中心、不依赖任何层。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 这是&amp;#34;整洁架构/洋葱架构&amp;#34;的思路，保证领域逻辑纯净。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="三依赖注入组装一切"&gt;&lt;a href="#%e4%b8%89%e4%be%9d%e8%b5%96%e6%b3%a8%e5%85%a5%e7%bb%84%e8%a3%85%e4%b8%80%e5%88%87" class="header-anchor"&gt;&lt;/a&gt;三、依赖注入：组装一切
&lt;/h2&gt;&lt;p&gt;ASP.NET Core 的 DI 是一等公民（见我的 ASP.NET Core 笔记一）。微服务里，&lt;strong&gt;所有跨层依赖都通过 DI 注入&lt;/strong&gt;，这样才好测试、好替换。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// OrderService.Application/Dependencies.cs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;AddOrderServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 应用层服务&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IOrderService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 端口适配器：接口在 Application，实现在 Infrastructure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IInventoryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InventoryClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IOrderRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// OrderService.Api/Program.cs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddOrderServices&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 业务服务&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHealthChecks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 健康检查（第五节）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHttpClientPolicies&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Polly 弹性（第六节）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapHealthChecks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/health&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 暴露健康检查端点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;单元测试里可以替换 &lt;code&gt;IInventoryClient&lt;/code&gt; 为 mock，这就是第四篇《.NET 单元测试：依赖注入与可测试性》的价值。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="四api-网关yarp-统一入口"&gt;&lt;a href="#%e5%9b%9bapi-%e7%bd%91%e5%85%b3yarp-%e7%bb%9f%e4%b8%80%e5%85%a5%e5%8f%a3" class="header-anchor"&gt;&lt;/a&gt;四、API 网关：YARP 统一入口
&lt;/h2&gt;&lt;p&gt;对外不直连各服务，用网关收口（第六篇）。.NET 生态用 &lt;strong&gt;YARP&lt;/strong&gt;（Yet Another Reverse Proxy，微软出品，比 Ocelot 更现代）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Gateway/Program.cs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddReverseProxy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadFromConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetSection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ReverseProxy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 路由放配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapReverseProxy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 网关入口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Gateway/appsettings.json —— 路由配置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ReverseProxy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Routes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;order-route&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ClusterId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;order-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Match&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;Path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/api/orders/{**catch-all}&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;inventory-route&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ClusterId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;inventory-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Match&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;Path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/api/inventory/{**catch-all}&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Clusters&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;order-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Destinations&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;d1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;Address&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://order-service:8080/&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;inventory-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Destinations&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;d1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;Address&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://inventory-service:8080/&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;网关集中处理（不在每个服务里重复）：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 路由（/api/orders → 订单服务）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 鉴权（统一验 token）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 限流、熔断
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 协议转换
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 生产环境再配多实例 + 负载均衡，保证网关本身高可用。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="五健康检查编排的基础"&gt;&lt;a href="#%e4%ba%94%e5%81%a5%e5%ba%b7%e6%a3%80%e6%9f%a5%e7%bc%96%e6%8e%92%e7%9a%84%e5%9f%ba%e7%a1%80" class="header-anchor"&gt;&lt;/a&gt;五、健康检查：编排的基础
&lt;/h2&gt;&lt;p&gt;K8s 和负载均衡器靠健康检查决定&amp;quot;流量往哪打&amp;quot;（第四篇分布式税）。ASP.NET Core 内置 HealthCheck。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 自定义健康检查：探测下游依赖&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InventoryHealthCheck&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IHealthCheck&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IInventoryClient&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;InventoryHealthCheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IInventoryClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HealthCheckResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;CheckHealthAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;HealthCheckContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PingAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;HealthCheckResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Healthy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;inventory reachable&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HealthCheckResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Degraded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;inventory slow&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HealthCheckResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unhealthy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;inventory down&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 注册&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHealthChecks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddCheck&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;InventoryHealthCheck&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;inventory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;failureStatus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HealthStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unhealthy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ready&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 分别暴露存活探针 / 就绪探针（K8s 标准用法）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapHealthChecks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/health/live&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Predicate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 进程活着&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapHealthChecks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/health/ready&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Predicate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ready&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;K8s 里：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; livenessProbe → /health/live （进程活着吗）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; readinessProbe → /health/ready （依赖就绪、能接流量吗）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 就绪探针失败 → K8s 把该实例摘出流量，但不重启；
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 存活探针失败 → K8s 重启容器。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="六弹性polly-应对分布式税"&gt;&lt;a href="#%e5%85%ad%e5%bc%b9%e6%80%a7polly-%e5%ba%94%e5%af%b9%e5%88%86%e5%b8%83%e5%bc%8f%e7%a8%8e" class="header-anchor"&gt;&lt;/a&gt;六、弹性：Polly 应对分布式税
&lt;/h2&gt;&lt;p&gt;跨网络调用要定义截止时间、并发和失败策略；重试与熔断并非越多越好。.NET 8 可用 &lt;code&gt;Microsoft.Extensions.Http.Resilience&lt;/code&gt;（基于 Polly v8）配合 &lt;code&gt;HttpClientFactory&lt;/code&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 需安装 Microsoft.Extensions.Http.Resilience&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHttpClient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IInventoryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InventoryClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://inventory-service:8080/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddStandardResilienceHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TotalRequestTimeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AttemptTimeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Retry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MaxRetryAttempts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Retry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DisableForUnsafeHttpMethods&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 写请求默认不自动重试&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;这几行代码对应第四篇的整笔账：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 超时 → 别傻等慢服务
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 重试 → 只处理适合重试的瞬时故障；写请求需先具备幂等键或去重语义
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 熔断 → 库存服务挂了，订单服务直接快速失败，不耗尽自己的线程池
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 切断雪崩的放大效应
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="七可观测性opentelemetry-串联"&gt;&lt;a href="#%e4%b8%83%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7opentelemetry-%e4%b8%b2%e8%81%94" class="header-anchor"&gt;&lt;/a&gt;七、可观测性：OpenTelemetry 串联
&lt;/h2&gt;&lt;p&gt;第七篇的链路追踪，几行代码接入。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 各服务统一接入 OpenTelemetry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddOpenTelemetry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTracing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddAspNetCoreInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// 自动追踪 HTTP 入站&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHttpClientInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// 自动追踪 HttpClient 出站&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSqlClientInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// 自动追踪 DB 调用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddOtlpExporter&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 导出到 OTel Collector&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddOpenTelemetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddOtlpExporter&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 活动上下文中的日志可关联 TraceId/SpanId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;效果：一次&amp;#34;下单&amp;#34;请求
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 网关(span) → 订单服务(span) → 库存服务(span) → DB(span)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 在采样、传播和各段 Instrumentation 正确配置时可连成一条 trace；异步消息还需显式传播上下文。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Jaeger 里一眼看到哪一段慢。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 这就是第七篇说的&amp;#34;微服务神经系统&amp;#34;，接入成本极低。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="八配置与外部化"&gt;&lt;a href="#%e5%85%ab%e9%85%8d%e7%bd%ae%e4%b8%8e%e5%a4%96%e9%83%a8%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;八、配置与外部化
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;每个服务的配置分环境（开发/测试/生产）外置：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; appsettings.json —— 默认值
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; appsettings.Production.json —— 生产覆盖
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 环境变量 / K8s ConfigMap / Secret —— 敏感和环境相关
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; builder.Configuration
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; .AddJsonFile(&amp;#34;appsettings.json&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; .AddJsonFile($&amp;#34;appsettings.{env}.json&amp;#34;, optional: true)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; .AddEnvironmentVariables(); // 环境变量优先级最高，适合容器
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 分布式税里的&amp;#34;配置中心&amp;#34;（Nacos/Apollo）在规模上来后再引入，
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 小系统先用环境变量 + ConfigMap 足够。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="九把前七篇串起来"&gt;&lt;a href="#%e4%b9%9d%e6%8a%8a%e5%89%8d%e4%b8%83%e7%af%87%e4%b8%b2%e8%b5%b7%e6%9d%a5" class="header-anchor"&gt;&lt;/a&gt;九、把前七篇串起来
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;这个骨架里，每一处都对应前面某一篇：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 工程结构、依赖方向 ← 第三篇：按领域切，单向依赖
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; DI 注入一切 ← 可测试性（ASP.NET Core 笔记四）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; YARP 网关 ← 第六篇：统一入口、路由、鉴权
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 健康检查 ← 第四篇：编排基础（K8s 探针）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Polly 超时/重试/熔断 ← 第四篇：弹性，防雪崩
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OpenTelemetry ← 第七篇：可观测性神经系统
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 服务间 HTTP + 幂等 ← 第五、六篇：一致性 + 通信
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 配置外置 ← 第四篇：分布式税中的配置
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 这就是一个&amp;#34;承重墙齐全&amp;#34;的微服务起点。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 业务往上长，基础设施已就位。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="十回到第一篇要不要这么做"&gt;&lt;a href="#%e5%8d%81%e5%9b%9e%e5%88%b0%e7%ac%ac%e4%b8%80%e7%af%87%e8%a6%81%e4%b8%8d%e8%a6%81%e8%bf%99%e4%b9%88%e5%81%9a" class="header-anchor"&gt;&lt;/a&gt;十、回到第一篇：要不要这么做
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;最后，回到系列第一篇的&amp;#34;权衡&amp;#34;：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 这个骨架是&amp;#34;当你要做微服务时&amp;#34;的标准起手式。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 但你要不要做微服务，回到那几个问题：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 团队是不是大到需要拆分协作？
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 是不是有独立扩容 / 独立发布 / 故障隔离的真实需求？
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 有没有 K8s + CI/CD + 可观测性的运维能力？
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 如果没有 → 第二篇的&amp;#34;模块化单体&amp;#34;才是你的答案。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 把这套骨架的&amp;#34;DI + 分层 + 健康检查 + 可观测性&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 用在单体内部，一样成立，还省了网络和分布式税。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 记住：技术选型服务于问题和约束，不是反过来。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="十一系列小结"&gt;&lt;a href="#%e5%8d%81%e4%b8%80%e7%b3%bb%e5%88%97%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;十一、系列小结
&lt;/h2&gt;&lt;p&gt;八篇下来，一条主线：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;（一）架构是权衡&lt;/strong&gt;：没有银弹，一切看约束&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;（二）单体被低估&lt;/strong&gt;：模块化单体是大多数团队的起点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;（三）拆分看领域&lt;/strong&gt;：按业务切，不按技术层切&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;（四）分布式要收税&lt;/strong&gt;：网络、一致性、可观测、运维，样样要自建&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;（五）一致性靠模式&lt;/strong&gt;：核心收敛强一致，周边用最终一致 + Saga + Outbox&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;（六）通信看同步异步&lt;/strong&gt;：REST/gRPC 与消息队列各擅其场&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;（七）可观测性是神经&lt;/strong&gt;：日志 + 指标 + 链路，traceId 串联&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;（八）落地 ASP.NET Core&lt;/strong&gt;：把理论变成可跑的代码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;架构没有终点。系统会演进，约束会变化，今天的最优解是明天的技术债。&lt;strong&gt;保持权衡的思维、演进的视角、记录决策的习惯&lt;/strong&gt;——这才是这套系列想留给你的，比任何具体技术都重要的东西。&lt;/p&gt;</description></item><item><title>后端架构实战（四）：微服务的“分布式税”——你准备好买单了吗</title><link>https://www.jiwei.space/posts/architecture/microservices/04-distributed-tax/</link><pubDate>Mon, 31 Mar 2025 10:00:00 +0800</pubDate><guid>https://www.jiwei.space/posts/architecture/microservices/04-distributed-tax/</guid><description>&lt;h2 id="写在前面"&gt;&lt;a href="#%e5%86%99%e5%9c%a8%e5%89%8d%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;写在前面
&lt;/h2&gt;&lt;p&gt;前三篇我一直在&amp;quot;劝退&amp;quot;过早微服务化，不是反对微服务，是想让你想清楚再拆。这一篇就把账算明白：拆成微服务之后，&lt;strong&gt;你到底要为哪些隐性成本买单&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;我把这些成本叫做“&lt;strong&gt;分布式税&lt;/strong&gt;”——单体里免费的东西，到了分布式环境，每一项都要你自己花人、花钱、花时间重新建起来。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一什么叫分布式税"&gt;&lt;a href="#%e4%b8%80%e4%bb%80%e4%b9%88%e5%8f%ab%e5%88%86%e5%b8%83%e5%bc%8f%e7%a8%8e" class="header-anchor"&gt;&lt;/a&gt;一、什么叫&amp;quot;分布式税&amp;quot;
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;单体里（进程内）免费的能力：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 函数调用 = 直接 new、直接调，纳秒级
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 强一致性 = 一个数据库事务搞定
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 配置 = 读本地配置文件
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 日志 = 写同一个文件
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 鉴权 = 一个进程内的中间件
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 故障传播 = 进程挂了，全挂（简单粗暴）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;微服务里（跨网络）每一项都要重新建：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 函数调用 → 网络调用（毫秒级、会超时、会丢包）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 同库事务 → 跨服务一致性设计（可能采用 Saga、TCC、Outbox、对账或分布式事务）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 配置 → 配置中心（集中下发、动态刷新）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 日志 → 日志聚合（收集到统一存储）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 鉴权 → 每个服务都要验 token
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 故障 → 一个挂了，可能雪崩倒一片
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 这些&amp;#34;重建&amp;#34;，就是分布式税。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="二第一笔税网络根本不可靠"&gt;&lt;a href="#%e4%ba%8c%e7%ac%ac%e4%b8%80%e7%ac%94%e7%a8%8e%e7%bd%91%e7%bb%9c%e6%a0%b9%e6%9c%ac%e4%b8%8d%e5%8f%af%e9%9d%a0" class="header-anchor"&gt;&lt;/a&gt;二、第一笔税：网络根本不可靠
&lt;/h2&gt;&lt;p&gt;这是分布式系统一切痛苦的根源。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;进程内调用 vs 网络调用：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 进程内调用：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ 几乎不会失败（除非进程崩）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ 纳秒~微秒级
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ 没有序列化开销
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 网络调用：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✗ 会超时（对方慢、网络抖动）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✗ 会丢包、会重试、会乱序
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✗ 毫秒级起步，还要序列化
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✗ &amp;#34;超时&amp;#34;最可怕——不知道对方到底执行了没有
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 八大谬误（Peter Deutsch）：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1. 网络是可靠的 ❌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 2. 延迟为零 ❌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 3. 带宽是无限的 ❌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 4. 网络是安全的 ❌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 5. 拓扑不会变化 ❌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 6. 只有一个管理员 ❌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 7. 传输成本为零 ❌
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 8. 网络是同构的 ❌
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;代价&lt;/strong&gt;：每一次跨服务调用都要定义超时与失败语义；是否重试、要求何种幂等、能否降级，要按操作和业务风险决定。&lt;code&gt;try-catch&lt;/code&gt; 本身在单体中也不能解决事务与恢复问题。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;网络为什么不可靠、CAP 为什么成立——我在《分布式系统学习笔记（一）：CAP 与一致性》里讲过底子。这里只说工程后果。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="三第二笔税服务发现与配置"&gt;&lt;a href="#%e4%b8%89%e7%ac%ac%e4%ba%8c%e7%ac%94%e7%a8%8e%e6%9c%8d%e5%8a%a1%e5%8f%91%e7%8e%b0%e4%b8%8e%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;三、第二笔税：服务发现与配置
&lt;/h2&gt;&lt;p&gt;单体里，所有代码在一个进程，互相调函数即可。微服务里，&amp;ldquo;找谁&amp;quot;和&amp;quot;用什么配置&amp;quot;成了问题。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;单体：函数地址 = 编译期固定
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;微服务：服务实例的 IP/端口是动态的（容器漂移、弹性扩缩）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;必须明确由平台、云服务或团队承担的能力：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 服务注册与发现（谁在线、在哪）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 常见：Consul / Nacos / etcd / K8s Service / Eureka
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 配置中心（配置不再散落各服务）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 常见：Nacos / Apollo / Consul KV / K8s ConfigMap
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 动态刷新（改配置不重启）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 这些都是单体里&amp;#34;不存在&amp;#34;的基础设施。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="四第三笔税数据一致性"&gt;&lt;a href="#%e5%9b%9b%e7%ac%ac%e4%b8%89%e7%ac%94%e7%a8%8e%e6%95%b0%e6%8d%ae%e4%b8%80%e8%87%b4%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;四、第三笔税：数据一致性
&lt;/h2&gt;&lt;p&gt;这是最重的一笔税，下一篇会专门展开，这里先列账：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;单体：一个事务保证 ACID
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;微服务：每个服务一个库，跨库没有 ACID
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;你必须明确选择或建设：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 分布式事务方案（Saga、TCC、Outbox 模式）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 最终一致性补偿机制
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 幂等性保证（重试导致的重复执行）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 对账机制（数据不一致时的人工/自动核对）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 详见我写的《分布式系统学习笔记（四）：分布式事务》。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 本系列第五篇会讲它怎么在数据架构上落地。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="五第四笔税可观测性"&gt;&lt;a href="#%e4%ba%94%e7%ac%ac%e5%9b%9b%e7%ac%94%e7%a8%8e%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;五、第四笔税：可观测性
&lt;/h2&gt;&lt;p&gt;单体里，一个请求的处理在一个进程内，看一个日志文件就懂了。微服务里，一个请求要经过 5 个服务，出问题你怎么定位？&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;必须具备可观测性“神经系统”，可自建也可使用托管服务：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 链路追踪（Trace）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 给每个请求一个 traceId，跨服务透传
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 常见：OpenTelemetry / Jaeger / Zipkin / SkyWalking
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 指标监控（Metrics）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 每个服务的 QPS、延迟、错误率
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 常见：Prometheus + Grafana
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 日志聚合（Logs）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 所有服务的日志收到一处，按 traceId 串联
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 常见：ELK / Loki
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 没有这三件套，微服务一旦出问题 = 黑盒，只能玄学排查。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 第七篇会专门讲可观测性。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="六第五笔税可靠性与弹性"&gt;&lt;a href="#%e5%85%ad%e7%ac%ac%e4%ba%94%e7%ac%94%e7%a8%8e%e5%8f%af%e9%9d%a0%e6%80%a7%e4%b8%8e%e5%bc%b9%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;六、第五笔税：可靠性与弹性
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;单体里：一个函数失败 → 抛异常，调用方决定怎么办
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;微服务里：一个服务失败 → 故障会沿调用链放大，可能雪崩
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;必须按调用风险配置：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 超时（Timeout）—— 别傻等
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 重试（Retry）—— 配合幂等
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 熔断（Circuit Breaker）—— 别打已经挂的服务
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 限流（Rate Limit）—— 别被流量压垮
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 降级（Fallback）—— 给个兜底响应
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 舱壁隔离（Bulkhead）—— 别让一个慢调用拖垮线程池
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; .NET 生态：Polly（这套东西几乎成了标配）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 本系列第八篇落地时会用上。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;雪崩示意：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 服务 A 依赖 B，B 依赖 C
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; C 慢了 → B 的线程被占满 → B 也慢 → A 的线程被占满 → A 也挂
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 一个底层小故障，逐层放大，拖垮整条链路。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 熔断 + 舱壁就是用来切断这种放大效应的。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="七第六笔税运维与部署"&gt;&lt;a href="#%e4%b8%83%e7%ac%ac%e5%85%ad%e7%ac%94%e7%a8%8e%e8%bf%90%e7%bb%b4%e4%b8%8e%e9%83%a8%e7%bd%b2" class="header-anchor"&gt;&lt;/a&gt;七、第六笔税：运维与部署
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;单体运维：1 个应用 × N 台机器
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;微服务运维：M 个服务 × N 个实例 × 动态变化
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 需要容器化（Docker）+ 编排（K8s）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 见我写的 Docker / K8s 系列
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 需要 CI/CD（每个服务独立构建、独立发布）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 需要版本兼容（新老接口并存期）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 需要 API 网关（统一入口、鉴权、限流）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 需要 DevOps 能力（SRE 文化）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 团队没有这些能力，上微服务 = 上灾难。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="八账单汇总值得吗"&gt;&lt;a href="#%e5%85%ab%e8%b4%a6%e5%8d%95%e6%b1%87%e6%80%bb%e5%80%bc%e5%be%97%e5%90%97" class="header-anchor"&gt;&lt;/a&gt;八、账单汇总：值得吗
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;拆成微服务，你要新增的基础设施清单：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; □ 服务注册发现 □ 配置中心
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; □ API 网关 □ 分布式事务/一致性
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; □ 链路追踪 □ 指标监控
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; □ 日志聚合 □ 熔断/限流/重试（Polly）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; □ 容器编排（K8s） □ CI/CD 流水线
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; □ 幂等 + 对账 □ 版本兼容策略
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 收益（只有规模到了才兑现）：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ✓ 独立部署、独立扩容、技术栈解耦、故障隔离、团队解耦
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 判断标准：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 规模/团队/解耦需求 带来的收益 &amp;gt; 上面这份税单 → 拆
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 否则 → 老老实实模块化单体
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 这就是第一篇说的&amp;#34;权衡&amp;#34;。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="九小结"&gt;&lt;a href="#%e4%b9%9d%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;九、小结
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;分布式税&lt;/strong&gt;：单体里免费的能力，微服务里每一项都要自建&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;网络不可靠&lt;/strong&gt;是根源：每次跨服务调用都要处理超时/重试/幂等/降级&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务发现 + 配置中心&lt;/strong&gt;：解决&amp;quot;找谁&amp;quot;和&amp;quot;用什么配置&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据一致性&lt;/strong&gt;是最重的税：Saga/最终一致/幂等/对账（下一篇详谈）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可观测性&lt;/strong&gt;：链路追踪 + 指标 + 日志，否则微服务是黑盒&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;弹性&lt;/strong&gt;：超时/重试/熔断/限流/降级/舱壁，防止雪崩&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;运维&lt;/strong&gt;：K8s + CI/CD + 网关 + 版本兼容&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;决策&lt;/strong&gt;：只有当解耦收益 &amp;gt; 这份税单，才值得拆&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下一篇，把最重的一笔税——&lt;strong&gt;分布式数据一致性&lt;/strong&gt;——彻底讲透。&lt;/p&gt;</description></item></channel></rss>