一文带你了解Monitor线程监控

如果您正在寻找一种有效方式,监控和管理Java虚拟机(JVM)中的线程,那这篇文章可太适合你啦!
本文详细介绍了Monitor线程监控工具,这是一种强大的实时分析工具,能够帮助您深入理解线程的运行情况和性能瓶颈。无论您是系统管理员还是性能分析师,通过本文的阅读,您将掌握使用Monitor工具优化系统性能的方法,性能问题的快速定位及解决将不再是难题,一起来看看吧~
功能简介
Monitor线程监控能够对 JVM 的当前线程堆栈快照进行分析,类似 Java 命令 Jstack,是实时分析线程运行情况和请求卡顿的好工具。
线程监控适用于当系统没有慢请求但存在卡顿的场景,我们可以通过持续观察系统所有线程状态,执行过程中查看线程信息、线程统计、当前方法、线程堆栈动态变化情况,综合分析定位出性能卡顿的根因。
适用版本
适用于所有版本,但不同版本界面稍有差异,本文将以金蝶云·苍穹V6.0.1版本的界面为例进行讲解。
功能入口
线程监控有两种查看方式,一种是在【注册中心】,选择某个服务实例,对单实例进行分析;另一种是在一级菜单【集群监控】→【线程监控】,对集群所有实例进行分析。

功能详情
1. 功能特性介绍
相对于 Jstack,线程监控工具支持了一些高效的增强功能:
可以按是否活跃、Web/服务/MQ/调度线程等维度进行过滤。一般只分析活跃线程。
按照时间降序排序,即执行时间越久的线程排名越靠前。通过刷新可以看到耗时久的线程,方便分析性能卡慢。
实时统计指标,当前线程运行过程中产生的指标,比如访问 db 次数,访问 redis 次数,一目了然知道该线程运行时间的消耗点。
当前执行方法的上下文,如当前方法是执行 sql,可以显示执行的 sql 语句及耗时,申请分布式锁,当前申请的锁 key,以及耗时。如果当前方法是性能瓶颈,很容易就能看出来问题。
跨节点调用关系,在集群线程监控中,对一次请求调用,如果存在调用关系,以并排方式显示,例如Web 线程=>MServiceBOS 线程。
2. 注册中心-线程堆栈
下面我们介绍【注册中心】下的线程堆栈功能。勾选某服务节点,点击“线程堆栈”,页面如下图:

首先,有 6 个页签用于过滤,分别表示:
All thread:查看所有线程。
Living thread:只查看活跃线程,包括 web 和服务线程。判断活跃线程的依据是堆栈行超过 20 行,不是 JVM 中 Thread 的状态为 Running,注意这个是和 Jstack 的差别所在。
Web request thread:只查看 Web Http 线程,一般情况,只有 Web 节点有 Web 线程,除非没有独立部署 Web 节点,MService 节点同时充当了 Web 的功能。
Living web request thread:只查看活跃 Web 线程。
Service thread:只查看 RPC 服务线程,如果 RPC 是用 Dubbo,那么就是 Dubbo 服务线程,如果 RPC 用 OpenFeign,那就是 OpenFeign 服务线程。无特殊说明,本文后续默认用 Dubbo 来说明。
Living service thread:只查看活跃 RPC 服务线程。
在页签下面一行,是线程状态统计值,这个状态是 Java 中 Thread 的状态,具体解释可以参考 Java 文档,包括:
TIMED_WAITING:指包含时间的等待线程,如sleep(timeout),wait(timeout)。
RUNNABLE:指运行中的线程。
WAITING:指等待线程,如 Object.wait。
BLOCKED:指受阻塞并且正在等待监视器锁的某一线程的线程状态。
在状态文本上悬浮,可以显示进一步的线程分类统计,如下图:

下面介绍“线程堆栈”的结构,如下图:

(1)线程信息
线程名:http-request-pool-75/traceId:4757f020037e5011/time:1700300282268,其中“http-request-pool-75”这部分是每种线程池初始化时的一个初始名称前缀。
通过这个能大概判断出线程的类型和作用,此处可以识别出是 web 调用的线程。
“traceId”是请求链路的唯一标识,该请求线程开始执行时是动态拼接的,请求执行完恢复原始的线程名。也有些线程没有traceId,说明该线程可能处于闲置状态,或者是一些第三方组件创建的线程。平台生成的线程真正执行的时机一般都有 traceId。
“time”是指当前线程开始执行请求的时间,即启动时间,也是动态拼接的,请求执行完恢复原始的线程名,但是这个要看启动这个线程的线程池是否会执行完一次任务就重置这个时间,也许有的线程不会。有的线程也没有这个,解释跟traceId 一样。
启动时间:就是 time 转化后的值,将 long 类型的值转为 Date 类型后的值就是启动时间。
已运行:当前时间减去启动时间得到已运行时间。
URL: 当前线程执行请求的路径。
TenantId:租户 ID。
UserName:当前操作的用户名。
FormId:表单名称。
Action:表单上执行的方法。
(2)线程统计
非常重要,指线程从启动到当前时间,发生的一些行为指标的统计信息,一般会包括 redis 访问、数据库访问、Orm 访问、插件执行等指标类型,统计值包括执行次数、总时间、平均时间。通过线程统计功能,通常就能够直观分析出本次线程执行中的主要耗时。
(3)当前方法
显示当前执行方法的信息,不是所有方法和时刻都能抓到,只有一些核心方法,刚好比较耗时的时候可以抓到,如下图所示,当前正在执行 SQL 查询,而 SQL也比较耗时,所以可以被看到。能够查看的方法主要有 SQL 执行、访问 Redis、微服务RPC 调用、申请分布式锁等。
开始时间是指当前方法已执行多少毫秒,执行方法是具体的方法描述,下面一行是该方法的参数,如 sql 语句,或者申请的分布式锁的 key,请看下图:

(4)线程堆栈
这个是通过 Java 程序的 Thread.getStackTrace() 获取到的当前时间点上,程序正在执行的调用路径。与 JVM 命令的 Jstack 得到的堆栈信息有一些区别。
3. 集群监控-线程监控
“线程监控”类似于注册中心的“线程堆栈”,区别是“线程监控”是从整个集群来分析线程的,具有更多的功能。一般来说,可以用本功能替代注册中心的“线程监控”。
线程展示结构和线程堆栈中介绍的类似,不再重复介绍,本节只介绍差异部分,如下图:

(1)过滤功能
使用者可以按照线程类型(活跃线程、Web 线程、服务线程,MQ线程等)、微服务、服务实例等维度进行过滤,也可以进行关键字或者排除关键字的过滤。
(2)集群排序
将整个集群所有节点的线程,按照耗时时长进行排序展示,故可以从整个集群范围查看耗时的线程,无需一个个节点打开分析。
(3)调用关系并列展示
对一次请求调用,如果存在调用关系,以并排方式显示,例如 Web 线程=>MServiceBOS 线程。如下图:

左边的堆栈信息是发起 http 请求时在 web 节点产生的堆栈信息,当前方法是在做跨节点服务 RPC 调用,右边是被调用节点当前的堆栈信息,通过==>来标识了调用方向。
该功能可以直观看到一个请求在节点上的调用拓扑,无需跨节点按 traceId 关系去查找。
对于稍瞬即逝的线程分析过程,分析的实时性直观性是非常重要的。
(4)死锁检测
当节点内 Java 发生死锁(即 synchronize,Object.wait 等产生的死锁,不包括 Java 轻量级锁),线程堆栈能在界面上方直接显示出来,如下图,前两个线程互相等待,导致死锁。关键字:“线程 1 Blocked on 锁对象 owned by Thread 线程 2”。

4. 新版线程监控
为了匹配
一文带你了解Monitor线程监控
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。



