知识卡片

舱壁隔离用局部线程池或信号量防止单点超时拖垮全局资源

普通读书笔记卡

内容

调用外部服务的故障可分失败、拒绝、超时三类,其中”超时”最危险——主流 网络访问基于”一个请求占一条线程”(TPR并发模型),请求不管最终成功还是 失败都要占着线程直到结束,而线程是整个系统级别的全局资源。如果某个 下游服务超时,按Tomcat默认20秒超时、每秒50次调用估算,20秒内就能吃掉 1000条用户线程,而Java应用线程池上限通常只有200~400,结果是这一个服务 的局部故障拖垮了整个系统的所有功能,而不只是依赖该服务的那部分。舱壁 隔离模式(名字来自造船业的水密舱设计——一个舱进水不会沉全船)针对性地 解决这个问题,有两种实现力度不同的手段。局部线程池:为每个远程服务 单独建一个专属线程池,故障服务最多只能阻塞它自己线程池里的那几条线程 (如设为5),不会波及全局线程池;代价是每个独立线程池都要承担排队、 调度、上下文切换的开销,Netflix给出的数据是启用Hystrix线程池隔离大约 给每次调用增加3~10ms延时,调用链有20次远程调用时总延迟代价可达 60~200ms。信号量机制:如果不需要主动清理线程池、中断线程这些额外能力, 只是想限制某服务的最大并发调用次数,可以只用一个线程安全的计数器—— 调用开始加1、返回减1,超过阈值就限流——不涉及线程排队调度,性能损耗 几乎可以忽略。舱壁隔离也不局限于服务调用层面,还可以在更宏观的粒度上 按功能、子系统、用户类型分流到独立实例,即使某个实例整体崩溃也只影响 部分用户。

参考来源

- 位置:《凤凰架构:构建可靠的大型分布式系统》第8章"流量治理"8.1.2节 "容错设计模式"(源文件:_epub-src对应OEBPS/Text/chapter99.xhtml) - 结论依据:原文用Tomcat 20秒超时+50 TPS估算出全局线程池会被单个故障 服务耗尽的具体数字,进而说明局部线程池能限制阻塞范围但带来3~10ms额外 延时,信号量机制无须排队调度、性能损耗可忽略,直接支撑本卡片结论。 - 原始内容:如果这样的访问量一直持续,我们按Tomcat默认的HTTP超时时间 (20s)来计算,20s内将会阻塞1000条用户线程……一旦启用Hystrix线程池来 进行服务隔离,大概会为每次服务调用增加约3~10ms的延时……信号量机制 ……相对于局部线程池来说几乎可以忽略不计。