线程池监控-bytebuddy-agent模式
目前已实现对线程池、jvm的监控;
主要是在线程池创建时,对线程池进行增强,将线程池强引用到bootstrap-load-client-0.1.jar中的ThreadPoolMonitorData里。 使用此包的前提是线程池是固定资源,启动后不会销毁,如果动态创建线程池并销毁,需要调用shutdown或者shutdowNow,这块已实现对对强引用的解除,否则因为这块强引用导致资源无法释放,没法被gc回收
bootstrap-load-client
此模块需要打成jar包
引入项目中;
配置bootstrap ClassLoader加载
monitor-agent
此模块需要打成jar包,当一个agent使用 启动参数配置
-javaagent:/Users/yxk/git/agent/monitor-agent/target/monitor-agent-0.1.jar=127.0.0.1,8888 -Xbootclasspath/a:/Users/yxk/git/agent/bootstrap-load-client/target/bootstrap-load-client-0.1.jar
说明:
monitor-agent-0.1.jar 为agent包
bootstrap-load-client-0.1.jar 为Bootstrap ClassLoader加载的包,在增强ThreadPoolExecutor的时候,必须是启动类加载
com.yxkong.agent目录结构
ByteBuddyAgent 为主类
增强ThreadPoolExecutor类
初始化httpServer
advice 为 具体的增强
dto 为传输包装
httpserver
实现了http服务(参考zabbix的jmx_exporter)
功能服务必须继承Collector,同时在构造方法里设置methodName,
实现collect 接口,就是具体要干的事,以及对应的返回参数
在ByteBuddyAgent.initHttpServer()方法中实例化一个对象并且register() 如 new ThreadPoolCollector().register();
主要实现功能
JVMCollector jvm的监控
StackCollector 当前栈信息收集
ThreadPoolCollector 线程池收集
ThreadPoolModify 线程池部分信息修改
注意事项:
线程池的ThreadFactory最好使用bootstrap-load-client-0.1.jar的NamedThreadFactory
否则无法获取线程池的名称和描述
针对没有使用NamedThreadFactory的ThreadPoolExecutor使用对象的hashCode做为key
测试
MonitorTest 控制台输出:
获取ThreadPoolMonitorData的类加载器:null #bootstrap classLoader 被屏蔽了,返回的是null获取ThreadPoolMonitorData收集的线程池:{}获取ThreadPoolMonitor的类加载器:sun.misc.Launcher$AppClassLoader@18b4aac2线程池pool执行中1:biz-pool-3-thread-1线程池pool执行中2:biz-pool-3-thread-2线程池pool执行中3:biz-pool-3-thread-3线程池executorService执行中1:pool-1-thread-1线程池启动完再获取收集的线程池:{"616881582":{"executor":{"activeCount":0,"threadFactory":{},"largestPoolSize":1,"poolSize":1,"taskCount":1,"rejectedExecutionHandler":{},"corePoolSize":0,"completedTaskCount":1,"terminating":false,"maximumPoolSize":2147483647,"queue":[],"shutdown":false,"terminated":false},"name":"616881582","desc":"未使用提供的NamedThreadFactory"},"biz":{"executor":{"activeCount":0,"threadFactory":{"name":"biz","desc":"业务执行线程池"},"largestPoolSize":3,"poolSize":3,"taskCount":3,"rejectedExecutionHandler":{},"corePoolSize":5,"completedTaskCount":3,"terminating":false,"maximumPoolSize":10,"queue":[],"shutdown":false,"terminated":false},"name":"biz","desc":"业务执行线程池"}}
jvm 数据获取 http://10.214.12.38:8090/jvm
{"data": {"JVM": {"specVersion": "1.8","unLoadedClassCount": 0,"javaVersion": "1.8.0_281","jitName": "HotSpot 64-Bit Tiered Compilers","jitTime": 1,"pid": "10866","totalLoadedClassCount": 3038,"version": "25.281-b09","specVendor": "Oracle Corporation","specName": "Java Virtual Machine Specification","loadedClassCount": 3038,"vendor": "Oracle Corporation","name": "Java HotSpot(TM) 64-Bit Server VM","startTime": 1618885248,"runTime": 19},"memory": {"oldGenMemoryUsage: ": {"init": 179306496,"usedPercent": 5.7213474E-6,"committed": 179306496,"max": 2863661056,"used": 16384},"permGenMemoryUsage: ": {"init": 0,"usedPercent": 0.0,"committed": 16646144,"max": -1,"used": 15378040},"permGenMemoryPeakUsage: ": {"init": 0,"usedPercent": 0.0,"committed": 16646144,"max": -1,"used": 15378072},"nonHeapMemoryUsage": {"init": 2555904,"usedPercent": 0.0,"committed": 23134208,"max": -1,"used": 21547992},"edenSpaceMemoryUsage": {"init": 67108864,"usedPercent": 0.011954648,"committed": 67108864,"max": 1409286144,"used": 16847520},"codeCacheMemoryUsage: ": {"init": 2555904,"usedPercent": 0.015820567,"committed": 3997696,"max": 251658240,"used": 3981376},"heapMemoryUsage": {"init": 268435456,"usedPercent": 0.0064246687,"committed": 257425408,"max": 3817865216,"used": 24528520},"oldGenMemoryPeakUsage: ": {"init": 179306496,"usedPercent": 5.7213474E-6,"committed": 179306496,"max": 2863661056,"used": 16384},"codeCacheMemoryPeakUsage: ": {"init": 2555904,"usedPercent": 0.015820567,"committed": 3997696,"max": 251658240,"used": 3981376},"survivorSpaceMemoryUsage: ": {"init": 11010048,"usedPercent": 0.72662354,"committed": 11010048,"max": 11010048,"used": 8000160},"survivorSpaceMemoryPeakUsage: ": {"init": 11010048,"usedPercent": 0.72662354,"committed": 11010048,"max": 11010048,"used": 8000160},"edenSpaceMemoryPeakUsage": {"init": 67108864,"usedPercent": 0.04761905,"committed": 67108864,"max": 1409286144,"used": 67108864}},"thread": {"threadCount": 13,"resetPeakThreadCount": 13,"daemonThreadCount": 5,"peakThreadCount": 13},"GC": {"fullGCName": "PS MarkSweep","YGCTime": 5,"fullGCTime": 0,"fullGCCount": 0,"YGCCount": 1,"YoungGCName": "PS Scavenge"}},"message": "执行成功!","status": "1","timestamp": 1618885268328}
线程池数据获取 http://10.214.12.38:8090/threadPool
{"message": "执行成功!","status": "1","data": {"biz": {"name": "biz","desc": "业务执行线程池","activeCount": 0,"largestPoolSize": 3,"poolSize": 3,"taskCount": 3,"corePoolSize": 5,"completedTaskCount": 3,"terminating": false,"maximumPoolSize": 10,"queueSize": 0,"shutdown": false,"terminated": false},"java.util.concurrent.ThreadPoolExecutor@892965953": {"name": "java.util.concurrent.ThreadPoolExecutor@892965953","desc": "未使用提供的NamedThreadFactory","activeCount": 0,"largestPoolSize": 1,"poolSize": 1,"taskCount": 1,"corePoolSize": 0,"completedTaskCount": 1,"terminating": false,"maximumPoolSize": 2147483647,"queueSize": 0,"shutdown": false,"terminated": false},"execute-pool-1": {"name": "execute-pool-1","desc": "default","activeCount": 1,"largestPoolSize": 1,"poolSize": 1,"taskCount": 1,"corePoolSize": 5,"completedTaskCount": 0,"terminating": false,"maximumPoolSize": 5,"queueSize": 0,"shutdown": false,"terminated": false}},"timestamp": 1618917221721}
线程池修改 http://10.214.12.38:8090/threadPool/modify?key=execute-pool-1&coreSize=3&maximumPoolSize=100
{"message": "执行成功!","status": "1","data": {"name": "execute-pool-1","desc": "default","activeCount": 3,"largestPoolSize": 3,"poolSize": 3,"taskCount": 3,"corePoolSize": 3,"completedTaskCount": 0,"terminating": false,"maximumPoolSize": 100,"queueSize": 0,"shutdown": false,"terminated": false},"timestamp": 1618917392869}
启动命令:
java -Xbootclasspath/a:/Users/yxk/git/agent/bootstrap-load-client/target/bootstrap-load-client-0.1.jar -javaagent:/Users/yxk/git/agent/monitor-agent/target/monitor-agent-0.1.jar -jar springboot-test-2.3.2.RELEASE.jar
使用zabbix或者别的监控工具,将对应的接口配置进去,完全可以实现对线程池的监控
