记录线上排查问题方法及流程01

        相信很多研发的小伙伴已经在网上get到了各种线程分析技能,我这里关于相关知识点就不展开叙述了。

 背景:

        项目某并行的任务进度不走卡在某一进度,服务CPU持续飙高,由于该任务是做数据预处理的(大量数据库操作),下级单位还等着用这个批次的数据,所以直接进行简短的现场排查。

1.检查jvm启动参数是否合理

 经查看启动jvm启动参数没有问题,jvm调参这个我们这里先不讨论

2.检查数据库 

 1.判断总条数是否异常。条数较多可怀疑有问题,并多次执行判断是否有哪些sql长期不消失

 oracle:

SELECT B.SID ORACLEID,
B.USERNAME 登录ORACLE用户名,
PADDR,
B.OSUSER,
B.MACHINE 计算机名,
B.SECONDS_IN_WAIT,
B.SQL_ID,
b.SQL_CHILD_NUMBER,
B.STATUS,
('alter system kill session ''' || b.sid || ',' || b.serial# || ''';') AS killsql,
(SELECT C.ELAPSED_TIME/1000000 FROM V$SQL C WHERE C.SQL_ID = B.SQL_ID and b.SQL_CHILD_NUMBER=c.CHILD_NUMBER) AS ELAPSED_TIME_累计秒,
(SELECT (case when EXECUTIONS=0 then 0 else C.ELAPSED_TIME/c.EXECUTIONS/1000000 end) FROM V$SQL C where C.SQL_ID = B.SQL_ID and b.SQL_CHILD_NUMBER=c.CHILD_NUMBER) AS 平均单次秒,
(SELECT C.SQL_TEXT FROM V$SQL C WHERE C.SQL_ID = B.SQL_ID and b.SQL_CHILD_NUMBER=c.CHILD_NUMBER) AS SQL_TEXT,
(SELECT C.SQL_FULLTEXT FROM V$SQL C WHERE C.SQL_ID = B.SQL_ID AND ROWNUM <= 1) AS SQL_FULLTEXT
FROM V$SESSION B
WHERE B.OSUSER <> 'oracle'
AND B.SQL_ID IS NOT NULL
ORDER BY 平均单次秒 desc nulls last;

 mysql:

select id, db, user, host, command, time, state, info from information_schema.processlist where command != 'Sleep' order by time desc

2.检查等待会话

3.检查是否有锁表

如何查询Oracle数据库表是否被锁_Zoe_YuZu的博客-CSDN博客_oracle查看是否锁表

数据库如果发现锁表,可以通过杀掉被锁的会话临时解决问题,发生这种问题最终还是要落实到代码中解决。

解决方法: 这种死锁是由于你的程序的'bug'产生的,除了调整你的程序的逻辑别无他法,仔细分析你程序的逻辑, 1:尽量避免同时锁定两个资源 2: 必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源. 

3.排查java线程栈

1.找到最耗CPU的进程

2.找到最耗CPU的线程

3.查看堆栈,定位线程执行逻辑,定位代码

1.使用 top -p <pid>(或者使用top -c按大写Pcpu排序) 命令(<pid>为Java进程的id号)按照cpu使用率排序查看Java进程的cpu占用:

 cpu已经被java进程占用了100.0%

2.使用 top -Hp <pid>  命令(<pid>为Java进程的id号)查看该Java进程内所有线程的资源占用情况

  发现一个线程把CPU线程占满了

3.这个时候我们可以选择做一下PID(7200)dump飞行记录等或者先将7200转换春耕16进制做整体java的线程记录

做线程dump方法:

使用dk自带命令jstack获取此时的线程快照并输入到文件中: jstack -l <pid> > ./jstack_result.txt 命令(<pid>为Java进程的id号)来获取线程快照结果并输入到指定文件。

4.查看堆栈,定位线程

1.当我们发现多个线程都占用非常高的CPU的时候

使用 printf "%x\n" <tid>  命令(tid指线程的id号)将以上10进制的线程号转换为16进制:

 转换后的结果分别为lc20,lc21,由于16进制以0x开头,所以对应的16进制的线程号为0xlc20和0xlc21。

 然后做整个java进程的线程dump

通过16进制线程号nid查看线程dump线程快照

示例:

2.直接做7200的线程dump(因为通过观察一个线程就把CPU打满,所以直接做一个就可以)

 

 

 直接锁定问题点,并通过@bci=12, line=965等信息直接锁定代码位置

接下来就是读代码时间了。。。

 4.除了线程快照可以帮助我们分析问题,我们还可以借助gc情况,cpu使用情况等

确认FGC次数是否频繁

重点看O列和FGC对应列,理想的情况O<90,并且15秒内FGC增长数<=1。

到这里基本上我们这次的排查也就结束了

 5.在最后附上我使用持续监控的脚本

抱大佬大腿

#!/bin/bash

while(true)
do

######################### 请按实际情况调整如下内容 #####################
#设置要监控的应用的端口
port=8080

#设置java_home所在路径
java_home=/data/jq/jdk1.8.0_181

#设置监控日志输出位置
output=/data/jq/xnjk
########################################################################

######################### 以下内容请不要随意调整 #######################
#初始化变量
pid=$(netstat -tlnp| grep $port | awk '{print $7}' |awk -F/ '{print $1}'|awk 'NR==1')
java_dir=$java_home/bin
dir_out=$output/xnjk_$port/`date +%Y%m%d`/`date +%Y%m%d_%H`/`date +%Y%m%d_%H%M%S`
mkdir -p $dir_out

#输出监控结果
ps H -eo user,pid,ppid,tid,time,%cpu,cmd --sort=-%cpu | awk 'NR<12{print}' >$dir_out/cpu_thread.log
top -p $pid -b -H -n 1 >$dir_out/cpu_top_"$pid".log
$java_dir/jstack $pid >$dir_out/threaddump_"$pid".txt
$java_dir/jstat -gcutil $pid >$dir_out/gc_"$pid".log
$java_dir/jstat -gc $pid >>$dir_out/gc_"$pid".log

#输出netstat监控
echo -e "`date +%Y%m%d_%H%M%S` \t $(netstat -anp | wc -l) \t $(netstat -anp | grep TIME_WAIT | wc -l)" >> $dir_out/netstat.log

#输出操作系统资源监控
vmstat -S M 1 15 >>$dir_out/vmstat_"$pid".log

#设置日志保留天数
num=3
#压缩最近n天日志,删除n天之前日志,n在上面设置,默认为3天
#一整天日志不压缩一般在1.5G以内,加上前几天压缩后的日志,总共占磁盘在2G以内
cd $output/xnjk_$port
for((i=1;i<=$num;i++))
do
  day_ago=`date -d "$i days ago" +%Y%m%d`
  if [ `ls | grep -v tar.gz | grep $day_ago |wc -l` -ne 0 ];then ls | grep -v tar.gz | grep "$day_ago" | xargs tar -czf $day_ago.tar.gz; fi
  ls | grep -v tar.gz | grep "$day_ago" | xargs rm -rf
  str="$str\|$day_ago"
done
ls | grep `date +%Y` | grep -v "`date +%Y%m%d`$str" | xargs rm -rf
########################################################################
done

https://download.csdn.net/download/qq_36448587/86248601

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值