知识卡片

框架代码要为业务方"想不到的用法"留余地:几万节点监控树引发的OldGC

普通读书笔记卡

内容

CAT团队遇到过一个真实案例:某位负责餐饮加商铺销售额统计的业务同事,在使用监控API时,把一个监控对象下面挂了几万个节点——这远远超出了设计者原本设想的正常使用规模,直接导致业务方的JVM出现严重的OldGC问题,反过来影响了业务本身的性能。这个案例背后的教训被总结成一句很值得记住的话:”框架的代码想象不出业务方会怎么使用你的代码,需要考虑到在任何情况下都有出问题的可能”——设计一个被广泛使用的底层框架或类库时,设计者自己脑海中预设的”正常使用场景”,永远只是所有业务方实际用法的一个子集,总会有业务方出于自己的具体需求,用一种设计者完全没有预料到的方式去使用这套API(比如把本该记录少量关键指标的监控对象,用来记录几万条明细数据),而这种”意料之外”的用法一旦触发框架内部没有针对性防护的薄弱环节(这里是无限增长的监控树导致的内存和GC压力),后果往往会被放大,因为框架代码通常运行在大量不同业务方的进程里,一次设计缺陷可能同时影响很多个业务。这条经验对任何面向内部多个团队提供公共基础能力的团队都有参考价值:设计公共API和框架时,除了考虑”这个功能该怎么设计才好用”,同样重要的是主动设想”如果有业务方用一种极端、甚至可以说是滥用的方式来调用这个API,会不会引发系统性的问题”,并针对这类极端场景设计防护机制(比如对单次调用能承载的数据规模设置合理上限),而不能假设所有使用者都会按照设计者预想的”正常方式”使用这套能力。

参考来源

- 位置:《高可用架构(第1卷)》第5章《运维保障》"5.2 深度剖析开源分布式监控CAT"节,"5.2.3 客户端设计"(源文件:_epub-src/OEBPS/Text/Chapter5_2_4.xhtml) - 结论依据:原文说明"我们的一位做业务的同事被请求做餐饮加商铺的销售额,在这种情况下……的一个监控对象就存在几万个节点,这会导致业务的OldGC情况特别严重。所以说框架的代码想象不出业务方会怎么使用你的代码,需要考虑到在任何情况下都有出问题的可能",直接支撑本卡片结论。 - 原始内容:我们的一位做业务的同事被请求做餐饮加商铺的销售额……的一个监控对象就存在几万个节点,这会导致业务的OldGC情况特别严重。所以说框架的代码想象不出业务方会怎么使用你的代码,需要考虑到在任何情况下都有出问题的可能。