13919049954

两起“蝴蝶效应”Cases

作者:金城在线 日期:2018/3/12 9:29:06 人气:37

最近碰到了两个case,一个是一个系统变慢了一点,导致另外一个系统暴露出ThreadLocal使用不当造成的小的故障;另外一个是一个小的边缘系统出现问题导致的严重故障。


Case One

有一个系统突然出现频繁的cms gc,dump内存后看到主要的消耗是在ThreadLocal里的一个对象,经过排查发现主要原因是在处理过程中有一个地方往ThreadLocal里塞了一个用来做cache的对象,但悲催的是每次会从ThreadLocal里先获取这个对象实例,然后塞一些对象到这个实例里的HashMap,而线程又是复用的,从而导致了HashMap里的对象不断的堆积,于是导致了故障。


这个Case最诡异的是突然出现,之前一直都运行的好好的,结果发现之所以出现是因为刚好这个系统依赖的后端一个系统变慢,而变慢后导致存活的线程变多,ThreadLocal里堆积的这些对象累积占用的内存也就变多了,刚好变多了后把本来剩余的那点内存给耗光了,所以频繁cms gc。


还有一种在线程复用下错误用ThreadLocal的方式是每次new ThreadLocal,在线程复用的情况下这会导致堆积很多的ThreadLocal对象,同样很容易导致内存用满。


所以通常我们都建议要慎重使用ThreadLocal,能不用最好是别用。


Case Two

一个超级重要的系统,突然出现vip挂掉,导致外部用户全部访问不到,在排查时突然又恢复了。


继续排查时,首先发现vip做健康检查时失败,对应的vip下的机器的访问日志里看到返回的http状态码是499,按照之前的经验,返回499都是因为后端处理慢导致的,而健康检查的文件是个静态文件,没任何逻辑,所以要造成这里处理慢只有一个原因,就是http的处理线程全部被耗光了。


于是观察那个时候这个系统依赖的几个主要点的响应时间,发现没什么变化。


http处理线程全部耗光,要知道原因最好的办法是在当时有问题的时候dump线程信息,但悲催的是当时没做dump,于是一摸黑,期望着通过系统日志来排查,结果是排查了一圈也没发现任何问题。


还好在这个时候某同学告知在故障出来之前有系统不太正常的现象,于是做了线程dump,捞到这个线程dump一看,http的处理线程大部分都在发起一个http请求,等待结果返回。


和业务方同学确认了下是什么请求,确认这只是一个页面发起的异步请求,而且很不重要,但从线程dump来看有可能是这个地方的问题,于是就找人去确认当时这个url对应的系统发生了什么,结果是在那个时间点刚好这个url对应的系统做了个动作,导致没有响应,而出故障的这个系统在发起这个http的请求时没设置超时,于是悲催了,所有处理线程被耗光,导致了vip健康检查失败。


这个故障聚集了以前出现过的严重故障的几个特征:

1. 一个不重要的系统出问题了导致了重要系统的故障,这主要原因就是隔离没做好,例如这种不重要的url的处理应该放在一个不重要的系统上去做,这样最多也就是那个不重要的系统挂掉;

2. 远程访问的超时,在高并发的系统里,任何的远程操作都必须设置超时(不过在上面的案例中仅仅设置超时是没用的,还是要靠隔离),而且超时不能设置太长(我做的服务框架第一个版本上线时就由于默认超时时间60s导致了严重故障)。


上面的这两起case其实都是一个系统的问题导致另外一个系统也出问题,这是互联网这类高可用性系统中最害怕的蝴蝶效应。


            金城在线专注网站、软件、APP、微信公众平台、小程序、抖音、头条等开发推广,如果您有这方面的需求或者不同的观点,欢迎联系交流。

    官方微信

    本文网址:http://lz.net.cn/zixunzhongxin/763.html
    读完这篇文章后,您心情如何?
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    更多>>网友评论
    发表评论