困扰好久的生产httpclient调用偶现socketTimeout异常

 

系统背景:

生产2台服务器,调用量高峰时期差不多15到20次每秒,每天差不多有50--80次的调用超时。之前也一直没有在意。后来观察日志发现,异常总是连续几次的出现,不是一次一次的,这个现象引起了我的注意。

 

后来因为一次优化需求,后台我将请求调用方式改为了线程池的异步调用:

 

private static ExecutorService threadPool = Executors.newCachedThreadPool();

 

主线程要等线程池任务运行完返回结果集,才可以继续运行,future来获取多线程返回结果,每个线程中的任务包含一个http请求调用,上线后,接口速度因为异步处理,所以提高了50ms左右,还算比较乐观,这样线程正常运行了一段时间,超时还是有,这个问题没有解决,因为没有定位出原因。

生产故障

某天晚上,服务调用方晚上搞活动,调用量增加了原先的2到3倍,晚上内存出现告警80%以上,运维人员查看内存使用情况,swap区域已经使用了60%以上。这下肯定是内存满了,晚上紧急情况,重启了应用,暂时恢复了正常。正确的流程应该是先下个dump文件,再重启的应用的。

 

第二天一早过来查问题,看系统运行情况,首先看jvm内存情况。

jstat -gcutil 25444 1000 20

 

发现比较异常的几个参数,Old区有将近90%左右,s0 和s1两者每次回收都有存留的值,正常应该一个是0的,最最要命的是FGCT几十次,正常情况下,只要JVM内存参数设置合理,是不会有这么多的FGC的,于是问了运维人员,他们配置的是默认配置(非专业运维人员…尴尬)于是乎我们开始调整jvm运行参数

-xms 初始堆大小    调整为512M

-xmx 最大堆大小    调整为2048M

-XX:PermSize 设置持久代的最大值  调整为256M    -----这个调整对FGCT的参数影响很大,说明之前FGCT次数过多和持久代内存不足有很大关系,推算系统static的代码区比较大

 

其他设置没做太大改动

 

修改之后,FGCT直线下降,次数很小,S0和S1运行正常,O区 0% 增长十分缓慢,观察一段时间后,各个区域运行正常。

 

好了,最最关键的来了,JVM调整参数之后,查看了一整天的日志,尽然没有一次SocketTimtOut

 

原因分析: 当系统FGC的时候系统会stop the world,所以在这段时间内,会出现短暂的连续的超时。

posted @ 2017-03-23 15:56  烜轩  阅读(4619)  评论(0编辑  收藏  举报