概述
目前从事的轨迹流服务,它是双机房多节点部署的。除了正式环境以外,还包括若干预发环境。本次事故介绍的是在预发环境上线出现的问题,解决办法和分析手段。
事故
服务A预发环境共有8台服务器,我先部署了三台。突然接收到线上正式A服务环境发出的报警,内容是存在部分下游机器的发送队列buffer超过阈值。当时没多想,先直接回滚代码。
后来分析,线上A服务均会向其预发环境发送数据(引流),发送逻辑是:遍历所有的预发服务机器,如果在buffer中的数据量小于设定阈值,则选取该机器,否则判断下一个;若都超过阈值,则会选取最后一个机器;因此线上服务发现新上的三台预发服务处理慢时,它会把请求打向其它未升级的正常预发服务。所幸的是,这次事故因此未对线上流量造成影响。
现象
更新的三台预发服务器,接收到的流量减半
其它服务器接收到的流量上升
从监控中看到每次tpc请求的时间开销是4ms,这表示新升级服务的处理速度变慢
问题分析
首先使用pstack命令,发现很多线程停留的位置都和一把锁相关。
A服务代码中有个全局的monitor,做相关数据的统计。有一把全局锁保护相关数据的更新。
本项目添加的代码中,有一部分更新的代码被“错误”的放入全局锁的作用域范围内了。导致锁作用的时间变长,线程间强锁的问题更加激烈。间接也导致了消息处理速度变慢。
问题修复
将所有更新的代码均挪到全局锁的作用范围之外。
数据对比
最大吞吐量比较
可见问题得到解决
总结
A服务存在一个全局锁,各线程间的碰撞较强。新添加的代码加重的锁的碰撞,造成吞吐量的下降。从cpu利用率上也能看出,cpu利用率远远没有达到饱和,这也间接说明了并没算力的原因造成的。