记 Arthas 实现一次 CPU 排查与代码热更新

简介: 线上代码经常会出现 CPU 占用过高的情况,按以往经验我会使用 top 指令,进一步借助于 jstack 去查看具体信息从而进行问题排查,但基本上都逃不过需要重新发包的局面,及时是一个增量包,应用也需要短暂停启。后来运维大兄弟让我试一下 Arthas,说是可以进行代码的热更新操作,正好来试一下。

作者 | 何波

【Arthas 官方社区正在举行征文活动,参加即有奖品拿~点击投稿

1.前言

背景

线上代码经常会出现 CPU 占用过高的情况,按以往经验我会使用 top 指令,进一步借助于 jstack 去查看具体信息从而进行问题排查,但基本上都逃不过需要重新发包的局面,及时是一个增量包,应用也需要短暂停启。后来运维大兄弟让我试一下 Arthas,说是可以进行代码的热更新操作,正好来试一下。

关于 Arthas 的安装与基础使用可以参考下面两篇文章:

  • Arthas 安装与监听 SpringBoot 应用
  • Arthas 基础指令使用说明

环境

JDK1.8 
SPringBoot 2.2.2
Arthas 
Linux

测试代码:

@RequestMapping(value = "/bigThread")
@ResponseBody
public String bigThread(int id) {ArthasService.test();while (true) {Thread t2 = new Thread();t2.start();id ++;if(100000 == id) {return String.valueOf(id);}}
}

思路

1.png

2.thread -b 查看是否有阻塞线程

thread -b, 找出当前阻塞其他线程的线程,执行完之后并未发现,说明该线程并非一直阻塞、一直执行的。

2.png

3.thread 查看占用最高的线程

当 thread 之后不跟参数时,显示当前全部线程信息,我觉得 thread -n 10,展示前 10 应该就够用,可根据实际需要自己决定。

下图可以很直观的看出,我们的应用瞬间占用了 77% 的 CPU(这里我是发起请求瞬间,通过 thread 查看的,所以比较直观,生产环境应该只有阻塞,死锁这种状态才会比较直观)。

3.png

4.thread id 查看具体信息

在上一步基础上,我们进一步查看,thread 15(因为上面的 ID=15)。

4.png

他的大致意思就是:线程在等待一个条件从而继续执行,可以看到方法是在执行 LinkedBlockingQueue.take 方法时候,查看这个方法的 API 提示如下:

public E take() throws InterruptedException {E x;int c = -1;final AtomicInteger count = this.count;final ReentrantLock takeLock = this.takeLock;takeLock.lockInterruptibly();try {while (count.get() == 0) {notEmpty.await();}x = dequeue();c = count.getAndDecrement();if (c > 1)notEmpty.signal();} finally {takeLock.unlock();}if (c == capacity)signalNotFull();return x;
}

其中:AtomicInteger 是保证高并发情况下的原子性,ReentrantLock 标识可重入锁,都是 JUC 包下需要了解的这里不赘述,需要的百度了解下。

这段代码关键点就在于:notEmpty.await(),从队列中消费数据,当队列为空是,线程阻塞,所以我们大致知道现在出现的问题是线程阻塞,但是还是不知道具体哪行代码的问题。

如果能够明确知道这次更改了哪些代码,可以直接执行步骤 6,不知道的话可以通过步骤 5 来定位问题。

5.watch 查看哪个 Controller 执行了代码

watch org.springframework.web.servlet.DispatcherServlet getHandler returnObj
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

这个脚本可以检测一切通过 DispatcherServlet 匹配 Handler 的方法,也就是进入 Controller 的请求,如下:

5.png

找到了对应的代码之后,我们来进一步观察异常信息,这里可能会有一个问题:就是我明明能通过日志去查看错误信息,为什么还需要这么繁琐的去操作。我的业务场景是:日志还是非常大的,刚捞到就被刷过去了,这时候定位日志不是很好操作,当然想捞下来日志肯定也是可以的,也很直观,我一般也都是去查看日志进行问题定位,这里也是提供一个思路。

6.watch 该方法异常信息

watch 类全路径 方法名 "{params[0],throwExp}" -e -x 2

6.png

如上,错误很直观的提示了出来,下面就可以修复解决了,这里我们也可以通过 trace 指令,查看执行时长:

trace 类全路径 方法名 "{params[0],throwExp}" -e -x 2

返回信息如下,也可以看到错误信息,和每个方法执行的时长。

[arthas@10999]$ trace com.arthas.controller.OrderController bigThread
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 53 ms, listenerId: 10
`---ts=2020-08-19 14:45:57;thread_name=http-nio-0.0.0.0-8080-exec-10;id=16;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6`---[1452.684406ms] com.arthas.controller.OrderController:bigThread() [throws Exception]+---[0.168814ms] com.arthas.service.ArthasService:test() #20`---throw:java.lang.OutOfMemoryError #-2 [unable to create new native thread]

7.jad 反编译热更新

在上面知道问题之后,我们就来定位问题就好了。

命令:jad 类全路径 方法名

[arthas@13190]$ jad com.arthas.controller.OrderControllerClassLoader:                                                                                                                                                                                
+-org.springframework.boot.loader.LaunchedURLClassLoader@17f052a3                                                                                                                           +-sun.misc.Launcher$AppClassLoader@3d4eac69                                                                                                                                               +-sun.misc.Launcher$ExtClassLoader@45f45fa1                                                                                                                                             Location:                                                                                                                                                                                   
file:/opt/software/arthas/Arthas.jar!/BOOT-INF/classes!/                                                                                                                                    /** Decompiled with CFR.* * Could not load the following classes:*  com.arthas.service.ArthasService*  org.springframework.stereotype.Controller*  org.springframework.web.bind.annotation.RequestMapping*  org.springframework.web.bind.annotation.ResponseBody*/
package com.arthas.controller;import com.arthas.service.ArthasService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class OrderController {@RequestMapping(value={"/bigThread"})@ResponseBodypublic String bigThread(int id) {ArthasService.test();do {Thread t2 = new Thread();t2.start();} while (100000 != ++id);return String.valueOf(id);}
}Affect(row-cnt:1) cost in 1513 ms.

此时代码就被反编译了,为了能够更改,所以我们需要输出为 java 文件。

指令:jad com.arthas.controller.OrderController > /tmp/OrderController.java

即:jad 类全路径 方法名 > 存储路径/存储名称

然后到 tmp 路径下 vi 修改 java 文件即可,修改完成之后,查看对应的 classloader 为编译做准备。

sc -d *OrderController | grep classLoaderHash
mc -c 17f052a3 /tmp/OrderController.java -d /tmp

7.png

但是这里编译出错了,官方提示:

8.png

所以我们本地编译好 class 文件,上传上去是一样的。

9.png

编译前调用

[arthas@13190]$ trace com.arthas.controller.OrderController bigThread
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 77 ms, listenerId: 2
`---ts=2020-08-19 15:51:46;thread_name=http-nio-0.0.0.0-8080-exec-1;id=d;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6`---[6734.666529ms] com.arthas.controller.OrderController:bigThread() [throws Exception]+---[0.786517ms] com.arthas.service.ArthasService:test() #20`---throw:java.lang.OutOfMemoryError #-2 [unable to create new native thread]

更新前代码

@RequestMapping(value = "/bigThread")
@ResponseBody
public String bigThread(int id) {ArthasService.test();while (true) {Thread t2 = new Thread();t2.start();id ++;if(100000 == id) {return String.valueOf(id);}}
}

更新后代码

@RequestMapping(value = "/bigThread")
@ResponseBody
public String bigThread(int id) {ArthasService.test();Thread t2 = new Thread();t2.start();return "success";
}

编译指令

[arthas@13190]$ redefine /tmp/OrderController.class
redefine success, size: 1, classes:
com.arthas.controller.OrderController

编译后调用三次

`---ts=2020-08-19 15:52:02;thread_name=http-nio-0.0.0.0-8080-exec-3;id=f;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6`---[5.609405ms] com.arthas.controller.OrderController:bigThread()`---[0.204675ms] com.arthas.service.ArthasService:test() #20`---ts=2020-08-19 15:52:04;thread_name=http-nio-0.0.0.0-8080-exec-4;id=10;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6`---[3.900149ms] com.arthas.controller.OrderController:bigThread()`---[0.14636ms] com.arthas.service.ArthasService:test() #20`---ts=2020-08-19 15:52:04;thread_name=http-nio-0.0.0.0-8080-exec-5;id=11;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6`---[1.90945ms] com.arthas.controller.OrderController:bigThread()`---[0.147353ms] com.arthas.service.ArthasService:test() #20

可以发现时间从 6734.666529ms 变成 3ms 左右,说明热更新的代码生效了。

8.profile 绘制火焰图做后续分析

如下图所示:

10.png

 

 

原文链接
本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/515142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

灵活、高效、智慧,宁畅发布新品及“智定+”战略

4月21日,2021宁畅新品暨战略发布会在京举办,宁畅发布了新品服务器“G40”系列,并推出 “智定”战略。该战略旨在智能时代为用户提供灵活、高效、智慧的定制化基础设施和服务。 图:2021宁畅新品暨战略发布会现场 宁畅总裁秦晓宁介…

应用系统瓶颈排查和分析的思考-Arthas 实战

简介: 业务应用系统接入流程引擎来处理业务应用的流程执行,流程引擎提供多线程高性能异步化来执行流程元素的执行,但是如何设置流程引擎的线程池线程数执行,以及执行线程数和任务数,应用机器资源使用情况之间的关系如何…

Java 虚拟机诊断利器

背景 最近学习Java字节码过程中遇到了反射,有段代码是这样的: package com.example.classstudy;import java.lang.reflect.Method;/*** author TY*/ public class ReflectionTest {private static int count 0;public static void foo() {new Excepti…

IDC报告:中国公有云服务市场同比增长49.7%,领跑全球

IDC最新发布的《全球及中国公有云服务市场(2020年)跟踪》报告显示,2020年全球公有云服务整体市场规模(IaaS/PaaS/SaaS)达到3,124.2亿美元,同比增长24.1%,中国公有云服务整体市场规模达到193.8亿…

是谁在调用我?使用 arthas+jprofiler 做复杂链路分析

简介: Arthas 是阿里巴巴开源的应用诊断利器,提供了 profiler 命令,可以生成热点火焰图。通过采样录制调用链路来做性能分析,极大提升了线上排查性能问题的效率。 作者 | 羽涅 阿里巴巴 CCO 技术部技术专家,承担 CCO …

Arthas 初探--安装初步适用

简介: 由于在项目中遇到一种情况,某段代码在进行单元测试和在 tomcat 容器中运行的性能相差数百倍,因此需要分析在不同环境下某个方法执行的具体时间,从而确定问题。Arthas 可以做到无侵入的监控应用远行情况。 作者 | agmtopy 由…

用 Arthas 神器来诊断 HBase 异常进程

1. 异常突起 HBase 集群的某一个 RegionServer 的 CPU 使用率突然飙升到百分之百,单独重启该 RegionServer 之后,CPU 的负载依旧会逐渐攀上顶峰。多次重启集群之后,CPU 满载的现象依然会复现,且会持续居高不下,慢慢地…

赠书 | 如何部署一个Knative Service

我们以一个go语言编写的程序代码为例,创建一个简单的Web服务,当该服务接收到HTTP GET请求时会根据环境变量TARGET传递的内容向response输出Hello $TATGET! 内容。1. 创建一个文件名为helloworld.go的文件。程序源码如下:package mainimport (…

一文读懂阿里云网络-SLB负载均衡新姿势

简介: 简介:负载均衡是洛神网络中最为关键的网元之一,其担负着网络流量分发的重任,有了它之后,用户在浏览应用的时候才能体会到“丝般顺滑”的感觉。欢迎免费体验SLB性能保障型负载均衡产品! 通过此文&…

聊聊缓存机制:双写兜兜转转,又回到了串行化

来源 | moon聊技术责编 | 寇雪芹头图 | 下载于ICphoto什么是双写?这个很好理解,双写就是说,一份数据在数据库存一份,在缓存中也存一份,给缓存一个过期时间,当读不到缓存时从数据库读出来然后写入缓存。为什…

如何基于大数据及AI平台实现业务系统实时化?

简介: 后疫情时代的新社会模式及经济形态必将催生出新的商业模式,在线业务及相关应用场景的流量呈现井喷式发展,常规的离线系统及离线机器学习平台已无法满足业务发展要求。 作者:高旸(吾与),阿…

基于 Flink 的典型 ETL 场景实现

简介: 本文将从数仓诞生的背景、数仓架构、离线与实时数仓的对比着手,综述数仓发展演进,然后分享基于 Flink 实现典型 ETL 场景的几个方案。 作者:买蓉 美团点评高级技术专家整理:赵阳(Flink 社区志愿者&…

商用密码技术与应用创新的方向是什么?安全牛发布《商密报告》全面揭晓

编辑 | 宋慧 出品 | CSDN云计算 头图 | 付费下载于东方IC 2021年4月22日,由安全牛举办的2021商用密码技术创新研讨会暨《2021商用密码创新应用指南》(以下简称《商密报告》)发布会在北京举行。 北京谷安天下科技有限公司副总裁贺晓辉在研讨…

Flink 源码 | 自定义 Format 消费 Maxwell CDC 数据

Flink 1.11 最重要的 Feature —— Hive Streaming 之前已经和大家分享过了,今天就和大家来聊一聊另一个特别重要的功能 —— CDC。 CDC概述 何为CDC?Change Data Capture,将数据库中的’增’、’改’、’删’操作记录下来。在很早之前是通…

阿里巴巴大数据实践:大数据建设方法论OneData

来源:数智化转型俱乐部 面对爆炸式增长的数据,如何建设高效的数据模型和体系,对这些数据进行有序和有结构地分类组织和存储,避免重复建设和数据不一致性,保证数据的规范性,一直是大数据系统建设不断追求的…

干货!一文搞懂无状态服务

来源 | 机智的程序员小熊责编 | 寇雪芹头图 | 下载于视觉中国事故的发生是量的积累的结果,任何事情都没有表面看起来那么简单,在软件运行的过程中,随着用户量的增加,不考虑高可用,迟早有一天会发生故障,不得…

后疫情时代,这家在线教育机构如何乘“云”而上

简介: 阿里云依托于云计算的基础设施特性,能够帮助教育机构避免业务侧重复投入、提高资源利用率、降低开发和运维成本,使洋葱学院激发出更大的活力,在后疫情时代得到更多用户的青睐 新冠疫情让现代人类和国际社会经历了大规模的隔…

2021全球权威AI性能竞赛MLPerf最新榜单: 浪潮获18项冠军几近半壁江山

4月22日,全球权威AI基准评测MLPerf公布2021年最新榜单,在全部有效41个项目中,浪潮获得18项性能第一,斩获几近半数冠军。 MLPerf™由图灵奖得主大卫•帕特森 (David Patterson)联合谷歌、斯坦福、哈佛大学…

NFS文件锁一致性设计原理解析

简介: 在存储系统中, NFS(Network File System,即网络文件系统)是一个重要的概念,已成为兼容POSIX语义的分布式文件系统的基础。它允许在多个主机之间共享公共文件系统,并提供数据共享的优势&am…

作为工程师,你真的了解无服务器?

译者 | 王欢来源 | 分布式实验室头图 | 下载于ICphoto最近,我在YouTube上看了一个非常出色的开发人员的视频。它的标题是“无服务器毫无意义”。虽然我非常喜欢该视频,但也不敢确定作者关于无服务器的观点是否完全正确,因此我想在本文中进行讨…