源码角度了解Skywalking之Skywalking是如何进行JVM监控的

大家都知道Skywalking可以监控Java的JVM情况,包括垃圾回收情况等等,那么它是怎么实现的呢?今天就带大家一探究竟。

通过前几篇的文章我们知道,Skywalking启动的时候,会加载各种BootService实现类,而有关JVM的BootService实现类就是JVMService

JVMService

JVMService可以看做一个定时器,它收集JVM cpu、内存、内存池和gc 信息等等参数,并将收集到的信息通过GRPCChannelManager提供的通道发送给Collector,GRPCChannelManager这个类我们在上篇文章我们就进行了介绍,主要是用来建立连接管理通道的

JVMService实现BootService接口和Runnable接口

我们按照调用方法的顺序分析一下吧

prepare()方法

JVMService的prepare()方法:

public static int BUFFER_SIZE = 60 * 10;
public void prepare() throws Throwable {queue = new LinkedBlockingQueue<JVMMetric>(Config.Jvm.BUFFER_SIZE);sender = new Sender();ServiceManager.INSTANCE.findService(GRPCChannelManager.class).addChannelListener(sender);}
复制代码

准备阶段就是创建一个LinkedBlockingQueue类型的阻塞队列,队列大小为600,这个队列保存的是JVMMetric对象,然后创建了一个Sender对象,找到GRPCChannelManager对象,并把Sender对象加入监听类中。

boot()方法

JVMService的boot()方法:

public void boot() throws Throwable {collectMetricFuture = Executors.newSingleThreadScheduledExecutor(new DefaultNamedThreadFactory("JVMService-produce")).scheduleAtFixedRate(new RunnableWithExceptionProtection(this, new RunnableWithExceptionProtection.CallbackWhenException() {@Override public void handle(Throwable t) {logger.error("JVMService produces metrics failure.", t);}}), 0, 1, TimeUnit.SECONDS);sendMetricFuture = Executors.newSingleThreadScheduledExecutor(new DefaultNamedThreadFactory("JVMService-consume")).scheduleAtFixedRate(new RunnableWithExceptionProtection(sender, new RunnableWithExceptionProtection.CallbackWhenException() {@Override public void handle(Throwable t) {logger.error("JVMService consumes and upload failure.", t);}}), 0, 1, TimeUnit.SECONDS);}
复制代码

boot()方法中定义两个定时线程池每隔一秒创建一个线程,一个是生产线程,一个是消费线程,生产者的逻辑对应JVMService的run()方法,而消费者的逻辑在Sender的run()方法中

run()方法

JVMService的run()方法:

public void run() {if (RemoteDownstreamConfig.Agent.SERVICE_ID != DictionaryUtil.nullValue()&& RemoteDownstreamConfig.Agent.SERVICE_INSTANCE_ID != DictionaryUtil.nullValue()) {long currentTimeMillis = System.currentTimeMillis();try {JVMMetric.Builder jvmBuilder = JVMMetric.newBuilder();jvmBuilder.setTime(currentTimeMillis);jvmBuilder.setCpu(CPUProvider.INSTANCE.getCpuMetric());jvmBuilder.addAllMemory(MemoryProvider.INSTANCE.getMemoryMetricList());jvmBuilder.addAllMemoryPool(MemoryPoolProvider.INSTANCE.getMemoryPoolMetricsList());jvmBuilder.addAllGc(GCProvider.INSTANCE.getGCList());JVMMetric jvmMetric = jvmBuilder.build();if (!queue.offer(jvmMetric)) {queue.poll();queue.offer(jvmMetric);}} catch (Exception e) {logger.error(e, "Collect JVM info fail.");}}}
复制代码

run()中的逻辑主要是创建JVMMetric对象,创建完成后放入队列中,从准备方法中我们知道队列大小设置是600,当队列满的时候,会取出最久的那个淘汰掉,然后放入新的JVMMetric对象到队尾。

从组装JVMMetric对象的过程我们可以看到,JVMMetric对象中包含了当前时间,CPU指标、内存指标还有垃圾回收指标。这三个指标的获取都是 利用枚举实现的单例模式 ,然后getGCList()方法中调用了GCModule抽象类的getGCList()方法,在获取新生代和老年代垃圾回收器名称的时候定义了抽象方法,具体逻辑每个垃圾回收器重写各自的抽象方法, 这是模板方法的体现

Sender

run()方法:

Sender对象作为消费者,它的功能就是通过drainTo()方法来把队列中的数据转移到buffer集合中,然后发送到Collector中。

总结

这篇文章我们讲了Skywalking是怎么进行JVM参数收集的,主要涉及到的类是JVMService,它的类定义了一个LinkedBlockingQueue类型的阻塞队列,长度是600,然后启动方法中启动了两个定时线程池创建了生产者JVMService线程和消费者Sender线程,JVMService作为生产者收集CPU、内存、垃圾回收信息等放入队列,Sender作为消费者从队列获取到所有JVM信息发送给Collector

:heart: 感谢大家

如果你觉得这篇内容对你挺有有帮助的话帮忙点点关注!

源码角度了解Skywalking之Skywalking是如何进行JVM监控的相关推荐

  1. Mybatis底层原理学习(二):从源码角度分析一次查询操作过程

    在阅读这篇文章之前,建议先阅读一下我之前写的两篇文章,对理解这篇文章很有帮助,特别是Mybatis新手: 写给mybatis小白的入门指南 mybatis底层原理学习(一):SqlSessionFac ...

  2. 从源码角度来读Handler

    最近打算从源码角度来读一下Handler,MessageQueue,Message,Looper,这四个面试必考项.所以今天先从Handler开始. 一.Handler的作用 源码定义 There a ...

  3. 从源码角度分析MapReduce的map-output流程

    文章目录 前言 流程图 源码分析 1 runNewMapper方法 2.NewOutputCollector方法 2.1 createSortingCollector方法 2.1.1 collecto ...

  4. 从源码角度入手实现RecyclerView的Item点击事件

    转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6758373.html RecyclerView 作为 ListView 和 GridView 的替代产物, ...

  5. 从JDK源码角度看Long

    概况 Java的Long类主要的作用就是对基本类型long进行封装,提供了一些处理long类型的方法,比如long到String类型的转换方法或String类型到long类型的转换方法,当然也包含与其 ...

  6. 【Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  7. 从源码角度看Android系统Launcher在开机时的启动过程

    Launcher是Android所有应用的入口,用来显示系统中已经安装的应用程序图标. Launcher本身也是一个App,一个提供桌面显示的App,但它与普通App有如下不同: Launcher是所 ...

  8. 从源码角度看Android系统SystemServer进程启动过程

    SystemServer进程是由Zygote进程fork生成,进程名为system_server,主要用于创建系统服务. 备注:本文将结合Android8.0的源码看SystemServer进程的启动 ...

  9. 从源码角度看Android系统Zygote进程启动过程

    在Android系统中,DVM.ART.应用程序进程和SystemServer进程都是由Zygote进程创建的,因此Zygote又称为"孵化器".它是通过fork的形式来创建应用程 ...

  10. 从源码角度解析Android中APK安装过程

    从源码角度解析Android中APK的安装过程 1. Android中APK简介 Android应用Apk的安装有如下四种方式: 1.1 系统应用安装 没有安装界面,在开机时自动完成 1.2 网络下载 ...

最新文章

  1. 不动的,稳定的,有序的东西就是低熵,相反的就是动的,不稳定的
  2. 人耳识别代码_语音识别之——音频特征fbank与mfcc,代码实现与分析
  3. python 声明变量类型_每日一课 | Python 检查变量的类型
  4. 【MySQL】如何最大程度防止人为误操作MySQL数据库?这次我懂了!!
  5. Spring 注入集合
  6. 起名与选择器~(总结类、持续更新系列)
  7. java form 上传文件_java通过表单进行文件上传的几种方法
  8. SeDuMi教程(1)
  9. SpringCloud工作笔记033---找不到import org.springframework.cloud.client.discovery.EnableDiscoveryClient;无法导入
  10. 滚~滚~滚动条(移动端 二)
  11. SpringMVC接受JSON参数详解
  12. 一封没有读出来的感谢信,勾勒出蔡文胜30年创业史!
  13. 摄氏温度和华氏温度相互转换(及其概念)
  14. ilo管理脚本 hponcfg方式
  15. Hadoop2.0高可用集群搭建【保姆级教程】
  16. 基于PHP的酒店管理系统
  17. 隧道工地考勤人员定位体系,提高施工人员作业安全-新导智能
  18. Mosquitto常用命令
  19. 《江南百景图》为什么火了?和主创团队聊完之后,我跪了
  20. 联通eMule的HighID设置方法

热门文章

  1. 怎么写解题步骤——FIRST集、FOLLOW集、LL(1)分析法【编译原理之语法分析】
  2. fadeIn()方法和fadeOut()方法
  3. 在GNU/Linux下将CD音乐转为mp3
  4. 2021年化工自动化控制仪表考试题库及化工自动化控制仪表报名考试
  5. 2.1微信小程序简介
  6. 第四章 信道与信道容量
  7. [割点问题]HOJ 12307 Disconnected Pair
  8. December in English(2017)
  9. android积分墙sdk,乐点 Android SDK 积分墙开发者文档
  10. python 常数赋值给tensor、常数和tensor比较大小、常数和tensor比较大小后作为tensor索引