@运维组
在因为性能或者其它各种问题决定通过重启恢复问题之前,先做一件事情:
找到一台或者两台将要重启的应用,执行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的工作原理,
HttpConnectionParams.setTcpNoDelay(httpParams, true);
为响应此接口,后台会有大量线程被占用
即使是现在
此接口还是很慢,系统崩溃的时候,我看到听云上的这个url占慢调用流程的70%以上
2016-06-29 12:52 | 40365 | |
2016-06-29 12:35 | 21521 | |
2016-06-29 12:38 | 21270 | |
2016-06-29 12:38 | 21240 | |
2016-06-29 12:38 | 21232 |
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进行访问
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) 必要的限流?
防止压力的传导?
保证核心业务?
=======================================