记录一次concurrent mode failure问题排查过程以及解决思路

背景:后台定时任务脚本每天凌晨5点30会执行一个批量扫库做业务的逻辑。

gc错误日志:

2017-07-05T05:30:54.408+0800: 518534.458: [CMS-concurrent-mark-start]
2017-07-05T05:30:55.279+0800: 518535.329: [GC 518535.329: [ParNew: 838848K->838848K(1118464K), 0.0000270 secs]
[CMS-concurrent-mark: 1.564/1.576 secs] [Times: user=10.88 sys=0.31, real=1.57 secs]
 (concurrent mode failure): 2720535K->2719116K(2796224K), 13.3742340 secs]
 3559383K->2719116K(3914688K),
 [CMS Perm : 38833K->38824K(524288K)], 13.3748020 secs] [Times: user=16.19 sys=0.00, real=13.37 secs]
2017-07-05T05:31:08.659+0800: 518548.710: [GC [1 CMS-initial-mark: 2719116K(2796224K)] 2733442K(3914688K), 0.0065150 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
2017-07-05T05:31:08.666+0800: 518548.716: [CMS-concurrent-mark-start]
2017-07-05T05:31:09.528+0800: 518549.578:
[GC 518549.578: [ParNew: 838848K->19737K(1118464K), 0.0055800 secs]
3557964K->2738853K(3914688K), 0.0060390 secs] [Times: user=0.09 sys=0.00, real=0.01 secs]
[CMS-concurrent-mark: 1.644/1.659 secs] [Times: user=14.15 sys=0.84, real=1.66 secs]
2017-07-05T05:31:10.326+0800: 518550.376: [CMS-concurrent-preclean-start]
2017-07-05T05:31:10.341+0800: 518550.391: [CMS-concurrent-preclean: 0.015/0.015 secs] [Times: user=0.05 sys=0.02, real=0.02 secs]
2017-07-05T05:31:10.341+0800: 518550.391: [CMS-concurrent-abortable-preclean-start]

借鉴于:understanding-cms-gc-logs

得知导致concurrent mode failure的原因有是: there was not enough space in the CMS generation to promote the worst case surviving young generation objects. We name this failure as “full promotion guarantee failure”

解决的方案有: The concurrent mode failure can either be avoided increasing the tenured generation size or initiating the CMS collection at a lesser heap occupancy by setting CMSInitiatingOccupancyFraction to a lower value and setting UseCMSInitiatingOccupancyOnly to true.

第二种方案需要综合考虑下,因为如果设置的CMSInitiatingOccupancyFraction过低有可能导致频繁的cms 降低性能。[参考不建议3g下配置cms:why no cms under 3G

问题排查:

1 jvm参数配置 -Xmx4096m -Xms2048m   -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSCompactAtFullCollection -XX:MaxTenuringThreshold=10 -XX:-UseAdaptiveSizePolicy -XX:PermSize=512M -XX:MaxPermSize=1024M -XX:SurvivorRatio=3 -XX:NewRatio=2 -XX:+PrintGCDateStamps -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails  几乎没什么问题

2 从报警时间看每天凌晨5点30报警一次, 应该是定时任务的问题。

该问题很容易排查,服务是个脚本服务,线上业务逻辑几乎没有,所以根据时间点找到定时任务的业务逻辑,就可以分析出来问题。

业务代码:

     int batchNumber = 1;
        int realCount = 0;
        int offset = 0;
        int limit = 999;
        int totalCount = 0;
        //初始化20个大小的线程池
        ExecutorService service = Executors.newFixedThreadPool(20);
        while (true) {
            LogUtils.info(logger, "{0},{1}->{2}", batchNumber, offset, (offset + limit));
            try {
                //分页查询
                Set<String> result = query(offset, limit);
                realCount = result.size();
                //将查询出的数据放入线程池执行
                service.execute(new AAAAAAA(result, batchNumber));
            } catch (Exception e) {
                LogUtils.error(logger, e, "exception,batch:{0},offset:{1},count:{2}", batchNumber, offset, limit);
                break;
            }
            totalCount += realCount;
            if (realCount < limit) {
                break;
            }
            batchNumber++;
            offset += limit;
        }
        service.shutdown();

用了一个固定20个线程的线程池,循环执行每次从数据库里面取出来999条数据放到线程池里面去跑

分析

newFixedThreadPool底层用了一个
LinkedBlockingQueue无限队列,而我的数据有2kw+条,这样死循环取数据放到队列里面没有把内存撑爆算好的吧???

最后换成
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(20);
ThreadPoolExecutor service = new ThreadPoolExecutor(20, 20, 1, TimeUnit.HOURS, queue, new ThreadPoolExecutor.CallerRunsPolicy());

用了个固定长度的队列,而且失败策略用的callerruns,可以理解为不能执行并且不能加入等待队列的时候主线程会直接跑run方法,会造成多线程变单线程,降低效率。

明天看看效果如何。

 
时间: 2024-10-16 12:27:37

记录一次concurrent mode failure问题排查过程以及解决思路的相关文章

Linux(2)---记录一次线上服务 CPU 100%的排查过程

Linux(2)---记录一次线上服务 CPU 100%的排查过程 当时产生CPU飙升接近100%的原因是因为项目中的websocket时时断开又重连导致CPU飙升接近100% .如何排查的呢 是通过日志输出错误信息: 得知websocket时时重新 连接的信息,然后找到原因 解决了. 当然这里幸好能通过日志大致分析出原因 那么我就在思考如果日志没有告诉任何信息 但线上CPU还是接近100%那么如何排查呢.所以学习了下排查过程. 通过查阅资料并实践后,这里总结了两种办法.第一种博客满天飞的方法

【问题记录】记一次ConnectionTimeout问题排查

最近做性能测试时,发现连接第三方系统时会有约1%的交易提示如下错误 nested exception is org.apache.commons.httpclient.ConnectTimeoutException: The host did not accept the connection within timeout of 10000 ms 起先抱着能google就google的思路去找,结果没找到相应的解决方案,只能自己一步一步去排查了,下面记录下排查过程. 抓拍问题现场 涉及到网络的问

一次线上页游服务器响应缓慢排查过程

最近线上一组服务器玩家反馈响应缓慢,记录下排查过程. 1.使用top命令查看服务器负载情况, top - 15:59:37 up 26 days,  3:42,  6 users,  load average: 2.98, 2.74, 2.70 Tasks: 180 total,   1 running, 167 sleeping,  12 stopped,   0 zombie Cpu(s):  8.1%us,  2.4%sy,  0.0%ni, 65.7%id, 23.6%wa,  0.0%

记一次erlang 节点CPU严重波动排查过程

新服务上线后观察到,CPU在10 ~ 70%间波动严重,但从每秒业务计数器看业务处理速度很平均. 接下来是排查步骤: 1. dstat -tam 大概每10s一个周期,网络流量开始变得很小,随后突然增大,CPU也激增. 网络流量变化和从性能计数器结果上并不符合,服务相关业务较为复杂,先找出那个业务占用网络流量. 2. iftop 找出流量最大的几个目标IP,并且周期的流量变为0随后激增. 通过IP 知道是外部http接口地址,因为接口调用是异步进行的,性能计算是执行开始记录的,而不是结束记录,因

一起数据库中过期用户数据堆积问题的排查过程

[文章摘要] 对于使用数据库来存放大量用户的软件来说,过期数据的清理机制需要慎重设计.如果设计不当,则会导致数据的误删除或清理不完全. 本文对某数据清理模块因参数配置不当而导致的过期用户数据堆积问题进行了详细的分析,为相关软件问题的分析及解决提供了有益的参考. 一.问题描述 在某软件系统中,为了让不同种类的用户享受对应的服务,引入了一个信箱服务等级的概念,即不同服务等级的用户具有不同的权限."一分钱,一分货",对于运营商来说,高服务等级的用户收取高的资费,提供高质量的服务. 为了维护不

记一次生产环境Nginx日志骤增的问题排查过程

摘要:众所周知,Nginx是目前最流行的Web Server之一,也广泛应用于负载均衡.反向代理等服务,但使用过程中可能因为对Nginx工作原理.变量含义理解错误,或是参数配置不当导致Nginx工作异常.本文介绍的就是福建开机广告Nginx的参数location处理静态文件配置不当引发的nginx日志骤增到14G的问题排期过程. 一.问题现象及系统介绍 现象:12月15日 21:02分,正在外面吃宵夜,手机收到监控平台的一条"服务器磁盘空间<20%"报警短信. 系统介绍:为了看此

解Bug之路-记一次中间件导致的慢SQL排查过程

解Bug之路-记一次中间件导致的慢SQL排查过程 前言 最近发现线上出现一个奇葩的问题,这问题让笔者定位了好长时间,期间排查问题的过程还是挺有意思的,正好博客也好久不更新了,就以此为素材写出了本篇文章. Bug现场 我们的分库分表中间件在经过一年的沉淀之后,已经到了比较稳定的阶段.而且经过线上压测的检验,单台每秒能够执行1.7W条sql.但线上情况还是有出乎我们意料的情况.有一个业务线反映,每天有几条sql有长达十几秒的超时.而且sql是主键更新或主键查询,更奇怪的是出现超时的是不同的sql,似

小问题不简单,一个无线故障的排查过程

本文不是为了说明解决了多难的问题,而是提供了查找app连接服务端的问题的几种解决问题的思路和方法 研发人员反映有个手机app业务在3G网络下刷新不了,是连接的测试环境的服务,通过办公网和wifi正常. 研发认为可能是在3G网络或者是服务器所在IDC机房问题,问题出现有一段时间了. 真这么神奇?专治疑难杂症30年的我得查查- 找来一台andriod手机,root过的,安装ssh终端模拟器app,希望直接连接网络进行测试. 发现能ping ,说明网络是通的,不能telnet服务端口. 想通过curl

使用maven时出现Failure to transfer 异常的解决办法

> 使用maven时出现Failure to transfer 错误的解决方法 在eclipse里使用maven,连接nexus私服. 添加依赖之后,总是报添加的依赖jar文件找不到,但是在nexus的库里面能找到这个依赖的jar文件,但是在本地的maven库里面找不到,于是我将本地库里面这个依赖对应的文件夹删掉,然后在eclipse里面执行update dependencies.成功解决问题! 右键单击项目->maven->update dependencies. 引起的原因是由于本地