金丝雀每个阶段该放多少流量、观察多久?蓝绿切换会不会丢请求?旧版本什么时候才能关?这篇用 nginx 1.31.6 的 reload 做真实的分阶段放量和切换,再用二项分布算发现概率。
重复 | 各阶段 canary 收到的请求数 / 其中的错误数 | 结果 | 用户一共看到的 503 ---+---------------------------------------------+-------------+------------ 1 | 1%:5个请求/0个错 → 5%:20个请求/4个错 → 25%:80个请求/6个错 | 25% 阶段发现并回滚 | 10 2 | 1%:2个请求/0个错 → 5%:26个请求/2个错 → 25%:111个请求/7个错 | 25% 阶段发现并回滚 | 9 3 | 1%:5个请求/0个错 → 5%:17个请求/1个错 → 25%:115个请求/8个错 | 25% 阶段发现并回滚 | 9 4 | 1%:5个请求/0个错 → 5%:17个请求/0个错 → 25%:99个请求/7个错 | 25% 阶段发现并回滚 | 7 1% 阶段 canary 只收到几个请求,5% 的错误率几乎肯定一个错误都没有;错误要攒够 5 个才报警,所以通常要到 25% 阶段才发现。越早放大比例,发现越快,但出事时受影响的用户也越多
小比例阶段攒不够错误,要到足够的比例才发现;放大越早发现越快,受影响的用户越多。
总请求率 | canary 比例 | 观察 10 s | 观察 60 s | 观察 300 s -------+-----------+-------------------+--------------------+------------------- 50/s | 1% | 5 个请求 · 0.0% | 30 个请求 · 1.6% | 150 个请求 · 87.4% 50/s | 5% | 25 个请求 · 0.7% | 150 个请求 · 87.4% | 750 个请求 · 100.0% 50/s | 25% | 125 个请求 · 75.4% | 750 个请求 · 100.0% | 3750 个请求 · 100.0% 200/s | 1% | 20 个请求 · 0.3% | 120 个请求 · 72.2% | 600 个请求 · 100.0% 200/s | 5% | 100 个请求 · 56.4% | 600 个请求 · 100.0% | 3000 个请求 · 100.0% 200/s | 25% | 500 个请求 · 100.0% | 3000 个请求 · 100.0% | 15000 个请求 · 100.0% 1000/s | 1% | 100 个请求 · 56.4% | 600 个请求 · 100.0% | 3000 个请求 · 100.0% 1000/s | 5% | 500 个请求 · 100.0% | 3000 个请求 · 100.0% | 15000 个请求 · 100.0% 1000/s | 25% | 2500 个请求 · 100.0% | 15000 个请求 · 100.0% | 75000 个请求 · 100.0% 需要的是 canary 本身收到的请求数,而不是总流量:总请求率低、比例小,就要观察更久;低流量的服务做金丝雀,窗口要按“攒够多少个请求”来定,而不是固定几分钟
按 canary 自己收到的请求数来定窗口,而不是固定几分钟。
做法 | 错误数 / 请求数 | 混合窗口(第一个 green 应答到最后一个 blue 应答) | 从 reload 完成到第一个 green 应答 -----------------------------+-----------+---------------------------------+------------------------- (a) reload 后保持 blue 运行 | 0 / 1200 | 75 ms | 2 ms (b) reload 后立刻 kill blue | 3 / 1200 | 没有重叠 | 4 ms (c) 同 (b),到后端用 keepalive 长连接 | 2 / 1200 | 没有重叠 | 8 ms nginx reload 之后,新的 worker 立刻用新配置接新连接,旧 worker 继续处理已经在它手上的请求和长连接直到处理完;所以 blue 要等旧 worker 把在途请求处理完再下线,立刻 kill 会让还在旧 worker 上的在途请求失败
reload 后新旧 worker 并存,旧版本要等在途请求处理完再下线。