快速失败比慢慢超时好。
一个请求等 30 秒后超时,占用了 30 秒的连接、线程和调用方的耐心。如果能在 2 秒内判断出"下游不可用"并返回明确错误,这 28 秒的资源就省下来了。快速失败不是放弃,是把资源腾给还能成功的请求。
不要让调用方猜你是慢还是死了。
同步调用超时后,调用方面对两种可能:你在处理但还没处理完,或者你已经挂了。两种情况需要完全不同的应对——前者应该等,后者应该切换。不给出明确信号就是把决策成本推给调用方。
回压是下游的权利,不是上游的施舍。
没有回压的系统里,上游决定发送速度,下游要么跟上要么被淹死。Reactive Streams 的设计把控制权交给了下游——下游告诉上游自己还能处理多少。这不是限流,是协商。限流是单方面拒绝;回压是双方合作。
同步调用是故障传播的高速公路。
A 同步调 B,B 同步调 C。C 挂了,B 的线程被阻塞,B 的线程池耗尽,A 调 B 也超时,A 的线程池也耗尽。一个下游故障沿着调用链反向传播,速度以毫秒计。消息驱动的异步架构把这条高速公路拆成了带缓冲的路段。
弹性不是"出了问题能恢复",是"出了问题时还能提供部分服务"。
恢复是事后的。弹性是实时的。一个有弹性的系统在数据库挂了的时候,还能用缓存提供读服务;在支付通道挂了的时候,还能让用户浏览商品。完全不可用才算故障。
隔离失败域的成本远低于级联故障的成本。
给每个组件独立的线程池、独立的连接池、独立的超时配置,看起来浪费资源。但一次级联故障造成的损失——用户流失、数据不一致、团队救火——通常是隔离成本的十倍以上。Bulkhead 模式的经济账算到这里就清楚了。
系统的真实容量不是峰值处理速度,是能持续运行不退化的最大负载。
压测跑出来的 QPS 峰值是"能到达但不能停留"的速度。有意义的指标是:在什么负载下系统能稳定运行 24 小时,延迟不升、错误率不涨、内存不泄漏。这个数字通常是峰值的 60%-70%。