记一次CPU使用分析

需求:服务器在某时段的CPU占用会规律性出现一段尖刺,现需每30s记录一次某服务器的系统资源使用状况,并且打印出CPU占用80%以上的线程堆栈信息,用于分析和优化。

jps命令 - 查看服务器当前进程

jps

top命令 - 动态查看系统资源使用

显示进程id为1的CPU使用情况

top -Hp 1

top
其中,要关注的主要指标是%CPU和%MEM,cpu和内存使用情况。

如果发现某线程的CPU占用超过阈值,比如80%,可以取出其PID,即线程id然后使用jstack进行堆栈分析。

jstack 查看线程堆栈

jstack 1 用来查看 Java 进程中所有线程的堆栈信息。如果要查看某线程的情况,使用jstack ${PID}。

jstack
其中,nid是16进制的线程id,需要转换后和top命令显示的PID匹配,然后把使得CPU高占用的线程堆栈情况打印出来(代码在脚本中)。

再次分析一下需求:每30s使用top命令查看一次CPU使用情况,取出其中CPU%超过阈值的线程,jstack命令查看堆栈情况。

shell脚本

文件存在/data/top下

# 判断文件夹是否存在,不存在则创建
if [ ! -d "/data/top" ]; then
  mkdir /data/top
fi

INTERVAL=30
  
# 在后台运行while循环
(
while true; do
  # 根据时间定义文件名
  now=$(date +%Y%m%d%H%M%S)
  log_file=/data/top/top_${now}.log
  jstack_log_file=/data/top/jstack_${now}.log

  # 3天前数据清理
  find /data/top -type f -mtime +3 -delete
  JAVA_PID=$(pgrep -f "java")
  # 保存top查询结果
  touch ${log_file}
  top -b -Hp ${JAVA_PID} -n 1 >> ${log_file}
  # 查询CPU高占用线程
  touch ${jstack_log_file}
  top -b -n 1 -Hp ${JAVA_PID} | awk '$9 > 80.0 {print $1} ' | while read PID  && [ -n "$PID" ]
    do
    	# 将PID转换为16进制
        hex_pid=$(printf '%x\n' $PID)
        echo "Thread dump for PID : $PID, PID(In hex) : $hex_pid"
        jstack $JAVA_PID | grep $hex_pid -A30  >> ${jstack_log_file}
    done &

  sleep $INTERVAL
done &

PID=$!
disown

echo "monitor Running in background, PID: $PID"

)

脚本可能存在的问题:在top命令和jstack命令之间有ms级的延迟,因此可能在top命令取出CPU%>80%的PID后,用jstack查看时,高CPU占用的步骤已经结束。

结论

将shell脚本在线上服务器在高峰时段运行,随机抽取log文件后分析,发现jstack文件里有效的几条是在打印日志。将kibana日志高峰时段相互印证,发现时间匹配,基本可以确定服务器高CPU%是由日志过多导致的。

在服务器上执行shell脚本的流程

# 1. 使用vi 创建文件
vi filename.sh

# 2. 把脚本内容复制进去
# 记得使用鼠标右键,因为ctrl+c,ctrl+v在console中不可用

# 3. 保存脚本
# esc 推出编辑模式,输入:wq ,按Enter进行保存,退出编辑器

# 4. 给脚本添加可执行权限
# chmod 改变文件权限; + x给文件添加可执行权限
chmod +x filename.sh

# 5. 运行脚本
./filename.sh

# 6. 记录PID并kill停止脚本
# 运行脚本后,会打印一个PID,如1694,再检查一下脚本是否正常运行
kill -9 1694

注意

  1. 如果vi编辑文件遇到冲突,需要先把当前文件相关线程kill掉,再修改
ps -ef | grep filename.sh

ps -ef
# 列出当前系统中运行的所有进程

grep filename.sh
# 筛选出含有 "filename.sh" 的行
  1. 查看文件 cat filename.sh
  2. 当使用cd /dir_name时,带有/是在根目录下,如果在当前文件夹下,则只需要cd dir_name
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值