近期遇到一些技术问题,记录如下:
1、NAS引起的惨案一
上次说到,大家都在降本,于是我们做了一系列调整工作。但降本总有一个永恒不变的主题:降配。
于是我们和集团的科技,同时开始了惨无人道的降配工作。
在一顿神奇操作后,系统终于区域稳定,好景不长,突然间又出问题了。
表现:
系统部分服务的部分节点,在服务高峰期之后,总是会出现时不时的系统卡顿。
关键这个卡顿很有规律,总是上午10点,下午4点出现,完美错过我们的上下午业务高峰。
原因:
经过技术委员会小伙伴通力排查,大家最终定位到是应用日志写入到归档NAS时,NAS性能十分不稳定,IO时间有时会高达几秒。
一旦遇到NAS卡顿,会阻塞日志,进而阻塞服务。
而且,当前NAS是和兄弟公司公用的,NAS卡顿时,正值他们的业务高峰期。
解决:
应用日志不再输出到NAS,而是输出到日志云。
2、NAS引起的惨案二
平稳度过了几天,周五,问题又来了。
表现:
系统时不时卡顿,没有任何规律,和业务高峰没有任何关系,一切监控都正常。
原因:
经过N个小时排查,我们的小伙伴,终于发现问题还是出现在日志上,只不过这一次,是GC日志。
GC日志同样是在归档NAS上,此时归档NAS更加不稳定,minor gc日志写入,偶尔会遇到NAS IO延时,引起系统卡顿。
解决:
应用日志不再输出到归档NAS,而是输出到中端闪存NAS,花钱买平安。
进一步:
针对当前遇到的情况,重新制定日志规范,尽快推广落地。
3、一次RefreshScope引发的惨案
表现:
使用nacos动态刷新了一个配置,但相关服务突然越来越慢,并有大量的锁等待:sun.misc.Unsafe.park
原因:
初步分析,nacos更新配置后,对应RefreshScope的类需要重新加载配置,从而调用了GenericScope类的destroy方法,在该方法中加了writelock
同时,业务代码在处理请求的时候,同样的用到了GenericScope::LockedScopedProxyFactoryBean的invoke方法,在该方法中加了readlock
先是读锁(多个),再写锁(一个),再读锁(多个),最后死锁了,都无法获取锁,服务就卡住了。问题是,一开始的锁为何不释放呢?
进一步分析,发现是在服务业务代码中,用到了HttpClient的org.apache.http.impl.io.SessionInputBufferImpl.streamRead方法
该方法调用了java.net.SocketInputStream.socketRead,该方法触发了jdk8的一个bug,该native方法无法返回
解决:
升级JDK版本,同时代码改造缩小RefreshScope的范围
4、一次redis引发的惨案
表现:
几分钟内redis内存飙高,直接爆掉。
查看了业务系统日志,没有出现业务激增的情况。
查看redis日志,发现AOF日志不断增大,重写的时候缓存爆掉,导致主备切换。
监控日志反馈存在大量setex操作。
原因:
reids集群出现大量setex操作,导致AOF日志激增,日志重写时落盘速度缓慢(出现了short write),结果AOF日志缓存爆掉,主从切换
解决:
临时升级了内存,后续将日志盘从NAS改为SSD,并好服务的redis主从切换配置
但setex激增的原因暂时还没有查到,补充了一些防御性代码