Java内存溢出和连接池死锁等各种混乱问题的解决

概述: 

    在对后端java抓取微博数据系统从1.0升级到2.0的过程中,产生了一些严重的问题,经过调整后,目前这些问题未再出现。 

问题1: 

    现象:前端页面数据混乱,A用户的数据混杂了B用户的数据,并且现象比较普遍。 

    原因:新浪基于JAVA语言SDK的V2版本存在BUG,有并发问题。 

          引起该问题的主要是SDK中的一个封装类:HttpClient。 

          因为该类为全局静态共享类,该类中的属性也同样成为全局共享类,在并发情况下,会导致部分属性的值被篡改,从而引起数据混乱。 

    解决办法:将该类中会导致并发问题的属性删掉,改为从方法参数中传入该值,改完后经反复测试,目前该问题未再复发。 

问题2: 

    现象:后端抓取日志出现连接池死锁、长时间获取mysql连接失败以及内存溢出异常的现象。该现象比较混乱,各种错误混到一起,使得查找问题都不太容易。 

    原因: 

         1,把java数据库连接池框架c3p0的日志打开后,发现c3p0存在死锁问题。 

         2,部分SDK接口短时间内会返回大量的数据,可能因此而导致堆溢出。 

         3,代码中的预处理sql会导致长时间获取mysql连接失败。 

    解决办法: 

         针对问题1:更换连接池,经过一番调查和比较之后,选定淘宝开源连接池druid。经部署测试后,死锁问题未再出现。 

         针对问题2: 

                    首先,错误日志显示为“java.lang.OutOfMemoryError: Java heap space”,于是增加java虚拟机的最大堆内存,后发现问题仍然存在内存溢出, 

                          不过错误日志信息变为了“java.lang.OutOfMemoryError: GC overhead limit exceeded”。 

                    其次,通过对错误日志的分析,发现每次出现该问题时,都会有“提到我的微博”等抓取任务在运行, 

                          于是修改了“提到我的微博”和“个人微博信息”等业务中每页返回的微博数,并调小部分代码中涉及到操作数的地方。 

                          同时修改carry端启动脚本,在java命令后加入参数“-XX:+UseGCOverheadLimit”,之后内存溢出问题消失。 

         针对问题3:这个问题找了很长的时间,调整了很多连接池的参数和java启动参数,并使用java内存监控工具分析和诊断。 

                    最初认为是连接的空闲时间过长,空闲连接未被释放导致该问题,于是在druid连接池中加入一个参数“removeAbandoned”, 

                    该参数会检测长时间未释放的空闲连接,若发现有这样的空闲连接并且空闲时间超过设定的时间,则会抛异常,并强行终止这种连接。 

                    通过连续监控,并未发现预料中的强行终止异常,问题仍然重现。 

                    最后通过对大量错误日志的分析,发现所有出现该问题的地方都会出现预处理sql,于是将代码中所有涉及到预处理sql的地方全都改成正常的普通sql,部署后问题未再出现。

来源:http://igoder.iteye.com/blog/1699666

    原文作者:java锁
    原文地址: https://blog.csdn.net/y88845601/article/details/47683255
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞