Linux下的JAVA程序CPU100%处理过程

JAVA程序CPU100%的处理过程

1.问题描述

最近在使用xxl-job做定时计算处理,写了10个定时任务,基本都是1分钟执行一次,之前开发中数据量较少,执行过程中没有问题。随着项目的被迫落地(一些客观原因导致的,开发的程序还并未做好完整的测试),现场的基础数据开始录入,给定时任务做性能测试,将现场的数据导入到测试环境。xxl-job定时程序大概经过一天的时间运行,过程中会出现2个问题:1.部署的xxl-job定时任务项目主机cpu100%,2.用户使用的项目中查询数据经常timeout

2.问题分析

只要将xxl-job定时项目进行重启后,另一个部署的用户使用项目的问题就会得到暂时的处理。先到定时项目主机中查询问题。
1)显示进程运行信息列表,执行命令:

top

在这里插入图片描述
2) 显示一个进程的线程运行信息列表,执行命令:

top -Hp pid

3)找到占用cpu最高的线程,将线程ID转换为十六进制,执行命令:

printf "%x\n" tid

4)查询线程堆栈信息,执行命令:

jstack pid|grep tid -A100

也可以直接将导出,执行命令:

jstack pid > tmp/pid.tdump

5)查询出的线程重点输出(部分省略):

"pool-8466-thread-4" #17372878 prio=5 os_prio=0 tid=0x0000000000758800 nid=0x6225 runnable [0x00007fe38c81e000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	at java.net.SocketInputStream.read(SocketInputStream.java:171)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at okio.Okio$2.read(Okio.java:140)
	...
	at com.influxdb.client.internal.AbstractWriteClient$ToWritePointsMaybe$$Lambda$3385/1512828004.apply
	at com.influxdb.client.internal.WriteApiImpl.close(WriteApiImpl.java:216)
	at com.xxl.job.executor.core.util.influxDB.InfluxDataUtil.qry(InfluxDataUtil.java:80)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

cpu高的线程基本都是在查询influxdb,因为程序中查询数据的实时值和历史值都需要查询influxdb

6)定位代码,看看代码中是否存在问题,避免因为代码的原因导致cpu问题,发觉在写InfluxDataUtil工具类的时候,在创建InfluxDBClient时,可进行优化:

	/**
	 * 连接时序数据库 ,若不存在则创建
	 * @return
	 */
	public InfluxDBClient influxDbBuild() {
		if (null == client) {
			client = InfluxData.getInfluxData();
			//client = InfluxDBClientFactory.create(url, token.toCharArray());
		}
		return client;
	}

不需要频繁创建,用单例模式保证系统中只此一份:

public class InfluxData {

	private volatile static InfluxDBClient client;
	private InfluxData(){}
	public static InfluxDBClient getInfluxData() {

		if (client == null) {
			synchronized (InfluxData.class) {
				//通过SpringUtils获取到注入的bean对象
				QryValParam qryValParam = (QryValParam) SpringUtils.getBean("qryValConfigExecutor");
				String url = qryValParam.getUrl();
				String token = qryValParam.getToken();
				if (client == null) {
					client = InfluxDBClientFactory.create(url, token.toCharArray());
				}
			}
		}
		return client;
	}



}

改变代码后,重新上传后,还是未能改变多少,因为一次查询influxdb就是一次tcp连接,数据量大无法改变,定时任务中有大量TIME_WAIT的线程,通过以下命令可查出:

netstat -apn | grep 8086 | grep TIME_WAIT | wc -l

7)改变策略:因为定时中查询实时值比查询历史值更多,那么在现场采集数据的时候写入influxdb的同时,也将最新的数据插入到redis中,查询实时值从redis中,减轻influxdb的连接压力
在这里插入图片描述
存储在redis中数据大概只占用2M。修改项目中查询实时值的代码后,重新发布,定时工程运行2天后,暂未出现100%的情况,后续再跟进。。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值