6.25,6.26(上周末)enterprise宕机问题分析

@运维组
在因为性能或者其它各种问题决定通过重启恢复问题之前,先做一件事情:  找到一台或者两台将要重启的应用,执行kill -3 pid, dump线程,最好执行三次,然后重启
此线程dump供开发观察出错时JVM中的线程,线程的数量,作用,状态,等待原因,是否有死锁发生
 
=================================
6.25,6.26(上周末) enterprise宕机问题分析:
 
过程描述:1)  周六下午出现了enterprise系统响应缓慢,卖家首页崩溃的问题,除了enterprise系统之外,bcwap,钱宝app,钱宝api,任务数据库都在报警,
                      后来运维回滚了钱宝api后,除了enterprise之外,其它系统全部恢复, enterprise重启多次问题无法解决,紧急回滚了enterprise版本,将周五上线的CAT监控功能移除,enterprise恢复工作
                
                    2)   周日中午再度出现上述问题,enterprise再度出现了系统响应慢,出错高,卖家首页崩溃。
                      此时除了enterprise系统之外,bcwap压力很大,拖累了www.qbao ,屏蔽bcwap后,www.qbao恢复正常,重启enterprise,可以短暂解决问题,2min后内存耗尽,内存加到12G,
                      一样无法恢复系统,后面采取了快速增加机器,将线上的enterprise app扩展到12台后,问题解决,系统恢复
 
分析和结论:
1  周六回滚enterprise版本,移除了CAT监控能力,系统恢复, 不排除CAT监控功能有问,这仅仅是一个怀疑的方向,可能和CAT也没啥关系,而是在移除CAT后,enterprise app依赖的系统刚好恢复了,
    导致了“误判是CAT有问题“,考虑到全民皆B,卖家首页承载着大量的功能入口,后续监控上线需要从其它不是很重要的系统入手,逐步推进。
 
2   enterprise宕机的原因是因为业务线程卡死,大量的业务线程处于等待状态,严重的场景下出现线程池耗尽,请求队列已满,直接拒绝服务
    在enterprise出错期间,我们发现www.qbao压力很大,反应迟钝,在卖家首页等前端页面,enterprise会定时发起(前台有定时任务)对www.qbao的请求,获取用户的公告信息,此远程调用基于HTTP,且没有      设置SO_TIMEOUT,在www.qbao没有给应答的情况下,业务线程会一直等应答(”一直“这个词语不够严谨,因为httpClient的版本可以不一样,enterprise的等很长时间,上千秒都是可能的),此时浏览器收不到应答,业务线程也不会被释放,  前端请求不断的发到后台,因为原先的业务线程处于等待状态,后台不断分配新的线程,新线程继续等,然后就是线程数暴增,后台线程因为获取www.qbao的数据而大量等待,直接导致此时对enterpsie的其它 请求也出现问题,干扰到全站的访问 

 

  a )  出错时,通过听云查看到的/sellerCenter/queryAnnounceAndIMInfo接口耗费时间几乎都在几十上百S以上,卖家首页等诸多页面都会定时拉取公告信息,此接口频度大,响应迟缓,结合tomcat的工作原理,
       为响应此接口,后台会有大量线程被占用
  
  即使是现在 此接口还是很慢,系统崩溃的时候,我看到听云上的这个url占慢调用流程的70%以上
b) 因为出错时,并没有及时dump thread,也没用听云来查看此时线程的工作状况,所以上面的结论都是静态推算出来的,但是结合tomcat的工作原理,结论的得出应该是可信的
 
3) 为什么会出现OOM? 
    fullGC后,发现内存还是不够用,才会出现OOM
   运维看到的OOM,可能真的是因为流量过大,应用程序扛不住了,不过调到12G都扛不住,是挺奇怪的
 
4) 加机器是解决问题的一个方法
   更多的机器,更多的请求处理资源,对于适合横向扩展提升处理能力的业务场景,好处是明显的。
   不过在过去,enterprise app线上就5台就撑住了请求, 现在改成了12台,发现每台机器的CPU,内存利用率都很低,应当是存在机器的浪费。
   存在机器浪费,说明运维可以在enterprise app的机器上继续放其它应用,并不代表着就需要减少机器的数量。
   减少机器,CPU利用率可以提升,但是GC压力也会变大,考虑到enterprise这个系统的的重要性,系统的容量设计,需要考虑到正常场景,极端场景,不建议运维为了省机器调整部署图
 
=============================
解决办法:
1  必须控制超时时间,防止服务提供方响应慢,导致调用方长时间等待.
    --- 超时时间设置,区分业务场景,有的接口需要一个长的超时,有的短超时,用dubbo很容易做到方法级别控制
         用httpCLient,写到utils里面,用一个可以普遍接受的时间
 
2 系统优化
   a) 此处只讨论RPC:  对于某些实时性不是那么强的数据,可以将请求结果在客户端缓存,设置过期时间,减少对外部系统的调用次数,
                                   实时性比较高的还是要实时调取,此时需要调用方保证性能
  b) enterprise各种配置相关的优化,这些参数对于其它组应该也有参考意义
       调整这些参数是为了业务线程池中的线程数,需要竞争的资源(数据库连接,http连接)数有一个合理的平衡
         1)  线上机器的server.xml配置 
            maxThreads="8000"  调整为 2048,看了线上正常情况下才200不到
        2) 数据库连接池配置
            目前线上的enterprise的“ 线上数据库支持的最大连接数配置”为5000
            而jdbc.properites的配置项,maxConnection是200,线上总共12台,将app的maxConnections加大为400,增大一倍
            让DBA看数据库连接,昨天下午的活跃连接才46个,数据库压力很小
        3)规范 httpClient的使用
           内部调用不建议每一次都重新建立连接释放连接,应该复用http连接池,httpClient是比较重的对象,有被share的必要,否则流量大的时候,频繁的打开关闭,对内存,IO都是额外的不必要的负担
          几个参数
            HttpConnectionParams.setConnectionTimeout(httpParams, 15000);
HttpConnectionParams.setSoTimeout(httpParams, 60000);
HttpConnectionParams.setTcpNoDelay(httpParams, true);
connectionManager.setMaxTotal(64 * 8*2); //创建socket的上线是1024个,过去是512个
connectionManager.setDefaultMaxPerRoute(256); // 对每个指定连接的服务器(指定的IP)最多可以创建256 socket进行访问

       4)  dubbo配置,目前采用的是默认优先,除了将timeout配置为60S,不额外优化线程等参数的配置,异步IO的吞吐效率非常高
       5) 线上统一将GC参数调整为  -Xms8196m -Xmx8196m  -Xmn4000m      之前已经调整为12G的tomcat,重新调整为上述配置,
           对于young generation为8G的内存,观察到机器的吞吐效率和4G 的没什么区别,内存根本用不完,而 minorGC的耗时达到了200ms,  超过 4G的100ms
      
3) 必要的压测:
  1   单台enterprise线上配置,空转性能
  2   压测首页的性能
 
4) 必要的限流? 
       防止压力的传导? 
       保证核心业务?
   
=======================================
      

猜你喜欢

转载自curious.iteye.com/blog/2308087