一个大对象引起的血案,GC的踩坑实录

背景:
 
问题:
有个渠道支付服务,负责与所有支付相关服务进行交互,包括 渠道下单支付,渠道成功通知,渠道的对账等
服务4台机,平时跑的都很稳定,通过thrift进行对外提供服务,且平时并未发现访问超时的情况,已经平稳在线上跑了1年多了,没出现过超时问题。
但最近发现,每天到了晚上凌晨2点开始大量服务访问超时,且定位到每次都是抢到对账任务的那台服务出现问题。
 
解决:
后通过监控和打印GC日志发现,出现问题机器服务的Major GC频率增加,应该是内存问题。
故把对账程序拆出后单独部署后, 再没出现服务访问超时情况。
 
分析,对账时,因为要捞出当天支付数据到内存进行对账(随着业务发展订单开始猛增)故触发了GC。其实增加分批limit当然也可以解决
这是最近第二次踩到GC的坑了, 第一次是每次访问给每个线程分配的内存过多,并发上来后性能严重降低,导致WEB超时,有必要总结下了
 
 
 
重现下:
 
死磕重现下,
 
模拟业务部分,假使每个业务需要500ms返回,代码如下:
复制代码
/**
 * 模拟当系统中使用大对象时,对JVM造成的影响
 * 
 * @author 包子(何锦彬). 2017.01.07
 * @QQ 277803242
 */
@WebServlet("/Test")
public class Test extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private Logger logger = Logger.getLogger(Test.class.getName());

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        long startTime = System.currentTimeMillis();
        // deal
        try {
            // 模拟业务花费时间
            Thread.sleep(500);
        } catch (InterruptedException e) {
        }
        long costTime = (System.currentTimeMillis() - startTime);
        // 接口1秒timeout,打印出日志
        if (costTime > 1000) {
            logger.warning("cost time:" + costTime);
        }
        Writer out = response.getWriter();
        out.append("ok");
    }
}
复制代码
 
放入tomcat,加入垃圾回收方式和堆内存大小,打印垃圾回收日志
 
JAVA_OPTS="-Xmx1200m -Xms1200m -Xmn200m -Xss228k -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+PrintGCDetails"
 
用jmeter压测1分钟后,发现正常,每次返回均在500毫秒左右,日志里也没有出现访问超时。
 
 
 
加入模拟对账部分代码,1分钟后对账开启,持续提供服务,为了让它触发GC,模拟加载了1G的待对账数据,(当然,在生产环境里只是一个大对象,但OU区本来就有东西了)
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值