卷 IV · 会不会炸CH 14深度 14/24

你离炸还有多远

上一章把「稳不稳」变成了一个整数,但整数是二值的:0 就是稳。而工程上你真正需要知道的是还剩多少余量——因为设备会老化、网络会多一跳、有人会给指标加个平滑。这一章给出两把标准尺子,其中一把能直接读成秒。

增益裕度相位裕度还能再晚多少秒

▷ 先拧一下

那台设备(K = 1,τ = 10 秒,L = 2 秒),纯比例控制,Kp = 4。它是稳定的(临界增益是 8.5024,我们只用了 47%)。

现在有人在这条链路里加了一个东西——一层代理、一个批处理窗口、一次重试——它给这个环增加了额外的纯延迟

问:能再加多少延迟,这个环才会开始自激振荡?

A 还能加 2 秒左右——毕竟增益只用了一半,延迟大概也能再翻一倍 B 还能加 2.71 秒,而且这个数可以直接算出来 C 还能加 6 秒以上,余量很大 D 说不准,得试

两把尺子

第 10 章那条判据说,失稳需要在同一个频率上同时满足两件事:相位滞后到 180°,且增益 ≥ 1

那么「离失稳还有多远」,自然有两种问法:

◆ 这一章的主线

增益裕度(gain margin,GM)
在相位刚好转到 −180° 的那个频率上,环路增益是多少?把它的倒数拿出来,就是「你还能把增益乘上几倍才会到 1」。

相位裕度(phase margin,PM)
在增益刚好等于 1 的那个频率上,相位还差多少才到 −180°?那个差额就是「你还能再往环里塞多少相位滞后」。

两把尺子量的是同一堵墙的两个方向:一把量「还能加多大力气」,一把量「还能多晚知道」。

拖动滑杆,上格是幅值、下格是相位,两条橙色的竖线就是那两把尺子:

Kp增益裕度(分贝)相位裕度还能再晚判定
24.251×12.57 dB100.2°10.09 s非常稳
42.126×6.55 dB60.1°2.71 s稳当
61.417×3.03 dB31.8°0.94 s偏紧
81.063×0.53 dB6.2°0.14 s危险
8.51.000×0.00 dB0.0°0.00 s就在墙上

先确认一件事:Kp = 8.5 那一行,两把尺子同时归零。这不是巧合——那正是临界点的定义。而 Kp = 4 时增益裕度是 2.126,正好是 8.5024 / 4 = 2.126增益裕度就是「临界增益除以你现在用的增益」。

那一列能读成秒

「还能再晚」那一列是这一章最有用的东西。它的换算只有一行:

   还能容忍的额外延迟 = 相位裕度(弧度) / 增益穿越频率

# Kp = 4 这一行:
   相位裕度 = 60.1° = 1.0489 弧度
   增益穿越频率 ωgc = 0.3873 rad/s
   还能再晚 = 1.0489 / 0.3873 = 2.71 秒

# 道理:纯延迟在频率 ω 上贡献的相位滞后是 ωL(第 10 章)。
#      所以要吃掉 PM 这么多相位,需要的延迟就是 PM/ωgc。

为什么这个数比相位裕度本身更有用?因为「度」是抽象的,「秒」是可以和现实对账的。

「这个环还有 60 度的相位裕度」——没人知道该拿这句话怎么办。
这个环还能再多容忍 2.71 秒的延迟」——这句话立刻可以变成决策:

  • 有人要在链路里加一层 API 网关,实测多 200 毫秒 → 占掉 7.4%,没问题。
  • 有人要把指标聚合窗口从 1 秒改成 5 秒 → 平均多 2.5 秒的延迟,直接吃掉 92%。这次评审必须拦下来。
  • 有人要加一次自动重试 → 失败时多一整个超时时间。这一条要按最坏情况算。

这就是把「稳定性」从一个玄学话题变成一笔账的方法。一个环的延迟预算,应该像内存预算、延迟预算一样被显式管理。

经验值:留多少合适

工业界有一组用了几十年的经验数字,值得记住:

           教科书推荐    含义
  ────────────────────────────────────────────────────
   增益裕度   > 2×        增益可以翻倍而不失稳
              (6 dB)    对应「设备特性变化一倍还扛得住」

   相位裕度   30° ~ 60°   低于 30° 会明显振荡、对延迟极其敏感
                          高于 60° 通常意味着你太保守了

★ 相位裕度还能直接换算成过冲(对二阶系统近似成立):
   PM ≈ 60°  →  过冲约 10%
   PM ≈ 45°  →  过冲约 25%
   PM ≈ 30°  →  过冲约 40%
# 粗略的口诀:ζ ≈ PM / 100。这也是为什么 60° 是个甜点 ——
# 它对应 ζ ≈ 0.6,正是第 4 章那张表里 9.5% 过冲的那一档。

回头看我们那张表:Kp = 4 时 PM = 60.1°,GM = 2.126×——两把尺子都恰好落在推荐区间的边上。这不是我挑的,是算出来的。而第 9 章那台设备在 Kp = 4、L = 2 的组合下冲过头 30.3%,比口诀估的 10% 大——因为口诀是给二阶系统的近似,而带纯延迟的系统严格说有无穷多个极点。口诀用来估数量级,不用来验收。

两把尺子都要看

一个常见的错误是只看其中一把。它们会在不同的场合失效:

只看增益裕度的盲区:有些系统增益裕度很大(你可以把增益乘 10 倍才失稳),但相位裕度极小——它对延迟非常敏感。这类系统在实验室里怎么调增益都很稳,一上线加了网络延迟就炸。

只看相位裕度的盲区:反过来的情况也有,尤其是当幅值曲线在 0 dB 附近走得很平的时候,增益一点点变化会让穿越频率大幅移动。

还有一类系统两把尺子都会骗你:幅值曲线多次穿越 0 dB、相位曲线多次穿越 −180° 的那种。这时候必须回到完整的奈奎斯特判据。本书不深入这一块,但你至少要知道它存在裕度是一个方便的简化,不是稳定性的定义。稳定性的定义仍然是上一章那个整数。

▸ 在现实里

为什么运维改配置要评审。「把健康检查间隔从 5 秒改成 30 秒」——这在功能上毫无影响,在延迟预算上是一笔大开销。如果你的自动摘除故障节点的逻辑是一个反馈环(它就是),那这次改动可能直接吃掉全部裕度。而没有人会在改配置时想到「稳定裕度」这四个字,因为没人算过它是多少。

「加个缓存」这件事的隐藏成本。缓存让读变快(这是好事),但它也让系统对变化的响应变慢——写下去的东西要过一会儿才被看见。如果这个读路径在某个反馈环里(限流、熔断、扩容都会读状态),那缓存 TTL 就是直接加进这个环的延迟。缓存是拿反馈的新鲜度换吞吐。

组织的相位裕度。一个团队在正常节奏下运转良好,加了一层汇报关系之后开始「一会儿冲一会儿刹」——那层汇报关系吃掉的就是相位裕度。而它常常被解释成「沟通不畅」或「新领导风格问题」,实际上是这个环的延迟预算被超支了

✗ 这个直觉是错的
裕度越大越好,应该尽量把系统设计得裕度很高。 裕度是买来的,而付账的是性能。相位裕度 100° 的那一行,Kp 只有 2——你的抗扰动能力、精度、响应速度全都只有原来的一半。

看那张表的第一行:Kp = 2 时相位裕度 100.2°、还能再容忍 10.09 秒的延迟,安全得不得了。而按第 5 章那个式子,它的抗扰动能力是 1/(1+2),Kp = 4 时是 1/(1+4)——你为那份安全付了 40% 的抗扰动能力。

所以裕度的正确用法不是「越大越好」,而是「够用就好,然后把剩下的全花掉」

  1. 先确定你的不确定性有多大:设备特性会变化多少?延迟最坏能到多少?这决定了你需要多少裕度。
  2. 留够这么多,剩下的力气全部用掉——因为没用掉的力气不会变成安全,只会变成缓慢和不准。

这也解释了那个 30°~60° 的经验区间从哪来:它是「典型工业设备的特性漂移和延迟波动」这个经验分布的产物,不是什么普适真理。如果你的对象特性极其稳定(比如一个纯电子回路),你可以放心用 30°;如果你的对象是一个会随天气、负载、版本变化的分布式系统,60° 可能都不够。

◈ 回读

B还能再加 2.71 秒,而且它是算出来的:相位裕度 60.1° 换成弧度是 1.0489,除以增益穿越频率 0.3873 rad/s,得 2.71 秒。

请注意这个数比原来的延迟(2 秒)大不了多少——虽然增益只用了临界值的 47%。「增益余量」和「延迟余量」不是一回事,也不成比例。

A 「增益只用了一半,延迟大概也能再翻一倍」——这个直觉把两把尺子当成同一把了。它的答案(2 秒)碰巧和正确答案(2.71 秒)接近,但推理是错的:增益裕度 2.126× 和延迟裕度 2.71 秒之间没有这种对应关系。换一组参数(比如 Kp = 6),增益裕度还有 1.417×,延迟裕度却只剩 0.94 秒了——比例完全不同。 C 「余量很大」——这是这一章想纠正的最主要的印象。一个「看起来稳当」的环(60° 相位裕度,教科书推荐区间的上沿),它能容忍的额外延迟只有两秒多。而两秒在一条真实链路上是很容易被吃掉的:一次重试、一层网关、一个五秒的聚合窗口,随便哪个都够。 D 「说不准,得试」——这一章存在的全部理由就是它可以不试。而且「试」在这里特别不可靠:你没法在生产环境上真的一点点加延迟直到它炸。能算出来的事情不要靠试,尤其是当「试」意味着把它弄坏的时候。

这一章的一句话

把「离炸还有多远」读成秒,稳定性就从一个玄学话题变成了一笔可以在评审会上算清的账。

下一章讲一个和裕度无关、却同样会毁掉一个环的东西:执行器有上限。当阀门已经全开、控制器还在纸上继续加大输出时,那个积分器会攒下一笔债——而这笔债还起来比欠下时慢一倍。同一个环,处理了这件事 41.1 秒回到目标,不处理 340.9 秒