故障隔离核心是控制资源边界,防止依赖异常拖垮服务:线程隔离通过独立线程池实现强隔离,适用于http、rpc等可能阻塞的调用;信号量隔离基于计数器限制并发,适用于本地缓存、内存计算等非阻塞高频操作。

故障隔离利用线程隔离与信号量机制,核心是控制资源使用边界,不让一个依赖的异常耗尽整个服务的处理能力。线程隔离通过物理资源切分实现强隔离,信号量隔离则用轻量计数方式限制并发,两者适用场景不同,但目标一致:让故障停在原地。
线程隔离:为每个依赖划出独立“工作间”
线程隔离本质是给每个外部依赖(比如订单服务、用户服务)分配专属线程池。这些线程池彼此不共享,即使某个依赖响应极慢或卡死,也只拖住它自己那几十个线程,Tomcat主线程池和其他依赖调用仍可正常流转。
- 适合场景:调用外部HTTP、RPC、数据库等可能阻塞的操作
- 关键配置:线程池大小需根据依赖的平均RT和最大QPS估算,避免过大浪费资源,过小导致排队超时
- 注意点:线程切换有开销,不适合毫秒级高频、纯内存计算类逻辑
信号量隔离:在原线程里“掐住并发数”
信号量隔离不新建线程,而是让调用直接在当前线程(如Tomcat线程)中执行,仅靠一个整型计数器控制同时最多有几个请求能进入该逻辑。一旦达到上限,后续请求立刻失败或走降级,不排队、不等待。
- 适合场景:本地缓存读写、内存计算、Redis命令等非阻塞、低延迟操作
- 关键配置:信号量容量设为合理并发阈值,例如本地缓存热点key访问控制在20以内
- 注意点:不能用于可能阻塞的调用,否则会把Tomcat线程卡住,反而影响全局
怎么选:看调用是否可能阻塞
判断依据很简单——这个调用会不会让当前线程停下来等结果。
- 会等:比如HTTP请求、JDBC查询、文件读取 → 必须用线程隔离
- 不会等:比如ConcurrentHashMap.get()、本地Caffeine缓存get、JSON序列化 → 可用信号量隔离
- 边界情况:Redis的Lettuce异步API是non-blocking,可用信号量;Jedis同步API是blocking,必须线程隔离
组合使用更稳健
真实系统中常混合使用。例如商品详情页:先用信号量控制本地缓存读取(快且无阻塞),缓存未命中时再用线程池调用远程商品服务(可能慢且阻塞)。这样既节省资源,又守住底线。
信号量负责“快路径”的并发压制,线程池兜底“慢路径”的资源熔断,双层防护让局部故障真正止步。










