spring监控(九)-JVM内存监控

概述

共有加载类、运行时、线程池、内存池和内存回收几大类指标

加载类

指标定义类

@Data
@NoArgsConstructor
public class ClassLoadingMetric {

    private long loadedClasses;
    private long totalLoadedClasses;
    private long unloadedClasses;
}

指标获取类

public class ClassLoadingProvider {

    private ClassLoadingMXBean mbean;
    
    public ClassLoadingProvider(){
        this.mbean = ManagementFactory.getClassLoadingMXBean();
    }
    
    public ClassLoadingMetric getClassLoadingMetrics(){
        ClassLoadingMetric metrics = new ClassLoadingMetric();
        metrics.setLoadedClasses(mbean.getLoadedClassCount());
        metrics.setTotalLoadedClasses(mbean.getTotalLoadedClassCount());
        metrics.setUnloadedClasses(mbean.getUnloadedClassCount());
        return metrics;
    }
}

运行时

指标定义类

@Data
@NoArgsConstructor
public class RuntimeMetric {
    private long startTimes;  // JVM启动时间点
    private long upTime;    // JVM运行时间
    private String specName;// Java虚拟机规范名称 
    private String specVersion;// Java虚拟机规范版本号
    private String vmName;// Java虚拟机名称 
    private String vmVersion;// Java虚拟机版本号
}

指标获取类

public class RuntimeProvider {
    private RuntimeMXBean mbean;
    
    public RuntimeProvider(){
        this.mbean = ManagementFactory.getRuntimeMXBean();
    }
    
    public RuntimeMetric getClassLoadingMetrics(){
        RuntimeMetric  metrics = new RuntimeMetric();
        
        metrics.setStartTimes(mbean.getStartTime());
        metrics.setUpTime(mbean.getUptime());
        metrics.setSpecName(mbean.getSpecName());
        metrics.setSpecVersion(mbean.getSpecVersion());
        metrics.setVmName(mbean.getVmName());
        metrics.setVmVersion(mbean.getVmVersion());
        
        return metrics;
    }
}

线程池

指标定义类

@Data
@NoArgsConstructor
public class ThreadMetric {

    private long totalThreads;  // 自JVM启动以来启动的所有线程数
    private long livingThreads;    // 当前activing的线程
    private long peakThreads;    // 线程数峰值
    private long daemonThreads;    // 守护线程数
}

指标获取类

public class ThreadProvider {
    private ThreadMXBean mbean;
    
    public ThreadProvider(){
        this.mbean = ManagementFactory.getThreadMXBean();
    }
    
    public ThreadMetric getClassLoadingMetrics(){
        ThreadMetric  metrics = new ThreadMetric();
        
        metrics.setDaemonThreads(mbean.getDaemonThreadCount());
        metrics.setPeakThreads(mbean.getPeakThreadCount());
        metrics.setLivingThreads(mbean.getThreadCount());
        metrics.setTotalThreads(mbean.getTotalStartedThreadCount());
        
        return metrics;
    }
}

内存池

JVM内存分为堆栈区和非堆栈区两个部分,这个是固定的。而对于内存池,有不同的实现,而不同的内存池其相应的指标名是不一样,因此应该区分获取。

JVM内存池指标定义

@Data
@NoArgsConstructor
public class JvmMemoryMetric {

    private long heapMax;
    private long heapUsed;
    private long heapAllocated;

    private long nonHeapMax;
    private long nonHeapUsed;
    private long nonHeapAllocated;

    private long permGenMax;
    private long permGenUsed;
    private long permGenAllocated;

    private long codeCacheMax;
    private long codeCacheUsed;
    private long codeCacheAllocated;

    private long edenMax;
    private long edenUsed;
    private long edenAllocated;

    private long oldMax;
    private long oldUsed;
    private long oldAllocated;

    private long survivorMax;
    private long survivorUsed;
    private long survivorAllocated;

    private long metaspaceMax;
    private long metaspaceUsed;
    private long metaspaceAllocated;
    
}

内存池接口

public interface MemoryPoolMetricAccessor {

    void fetchMemoryPoolMetrics(JvmMemoryMetric memoryMetric);

}

内存池基础类

public abstract class MemoryPoolModule implements MemoryPoolMetricAccessor {
    
    private MemoryPoolMXBean[] beans;

    public MemoryPoolModule(List<MemoryPoolMXBean> beans) {
        this.beans = beans.toArray(new MemoryPoolMXBean[0]);
    }

    @Override
    public void fetchMemoryPoolMetrics(JvmMemoryMetric memoryMetric) {
        
        // 循环每个内存区域,收集每个 MemoryPool 指标
        for (MemoryPoolMXBean bean : beans) {
            String name = bean.getName();
            MemoryUsage usage = bean.getUsage();
            // 获得内存区域类型
            if (contains(getCodeCacheNames(), name)) {
                memoryMetric.setCodeCacheMax(usage.getMax());
                memoryMetric.setCodeCacheUsed(usage.getUsed());
                memoryMetric.setCodeCacheAllocated(usage.getCommitted());
            } else if (contains(getEdenNames(), name)) {
                memoryMetric.setEdenMax(usage.getMax());
                memoryMetric.setEdenUsed(usage.getUsed());
                memoryMetric.setEdenAllocated(usage.getCommitted());
            } else if (contains(getOldNames(), name)) {
                memoryMetric.setOldMax(usage.getMax());
                memoryMetric.setOldUsed(usage.getUsed());
                memoryMetric.setOldAllocated(usage.getCommitted());
            } else if (contains(getSurvivorNames(), name)) {
                memoryMetric.setSurvivorMax(usage.getMax());
                memoryMetric.setSurvivorUsed(usage.getUsed());
                memoryMetric.setSurvivorAllocated(usage.getCommitted());
            } else if (contains(getMetaspaceNames(), name)) {
                memoryMetric.setMetaspaceMax(usage.getMax());
                memoryMetric.setMetaspaceUsed(usage.getUsed());
                memoryMetric.setMetaspaceAllocated(usage.getCommitted());
            } else if (contains(getPermNames(), name)) {
                memoryMetric.setPermGenMax(usage.getMax());
                memoryMetric.setPermGenUsed(usage.getUsed());
                memoryMetric.setPermGenAllocated(usage.getCommitted());
            } else {
                continue;
            }
        }
    }

    private boolean contains(String[] possibleNames, String name) {
        for (String possibleName : possibleNames) {
            if (name.equals(possibleName)) {
                return true;
            }
        }
        return false;
    }

    protected abstract String[] getPermNames();

    protected abstract String[] getCodeCacheNames();

    protected abstract String[] getEdenNames();

    protected abstract String[] getOldNames();

    protected abstract String[] getSurvivorNames();

    protected abstract String[] getMetaspaceNames();
}

CMSCollector内存池类

public class CMSCollectorModule extends MemoryPoolModule {
    public CMSCollectorModule(List<MemoryPoolMXBean> beans) {
        super(beans);
    }

    @Override 
    protected String[] getPermNames() {
        return new String[] {"CMS Perm Gen", "Compressed Class Space"};
    }

    @Override 
    protected String[] getCodeCacheNames() {
        return new String[] {"Code Cache"};
    }

    @Override 
    protected String[] getEdenNames() {
        return new String[] {"Par Eden Space"};
    }

    @Override 
    protected String[] getOldNames() {
        return new String[] {"CMS Old Gen"};
    }

    @Override 
    protected String[] getSurvivorNames() {
        return new String[] {"Par Survivor Space"};
    }

    @Override 
    protected String[] getMetaspaceNames() {
        return new String[] {"Metaspace"};
    }
}

G1内存池类

public class G1CollectorModule extends MemoryPoolModule {
    public G1CollectorModule(List<MemoryPoolMXBean> beans) {
        super(beans);
    }

    @Override 
    protected String[] getPermNames() {
        return new String[] {"G1 Perm Gen", "Compressed Class Space"};
    }

    @Override 
    protected String[] getCodeCacheNames() {
        return new String[] {"Code Cache"};
    }

    @Override 
    protected String[] getEdenNames() {
        return new String[] {"G1 Eden Space"};
    }

    @Override 
    protected String[] getOldNames() {
        return new String[] {"G1 Old Gen"};
    }

    @Override 
    protected String[] getSurvivorNames() {
        return new String[] {"G1 Survivor Space"};
    }

    @Override 
    protected String[] getMetaspaceNames() {
        return new String[] {"Metaspace"};
    }
}

Parallel内存池类

public class ParallelCollectorModule extends MemoryPoolModule {

    public ParallelCollectorModule(List<MemoryPoolMXBean> beans) {
        super(beans);
    }

    @Override 
    protected String[] getPermNames() {
        return new String[] {"PS Perm Gen", "Compressed Class Space"};
    }

    @Override 
    protected String[] getCodeCacheNames() {
        return new String[] {"Code Cache"};
    }

    @Override 
    protected String[] getEdenNames() {
        return new String[] {"PS Eden Space"};
    }

    @Override 
    protected String[] getOldNames() {
        return new String[] {"PS Old Gen"};
    }

    @Override 
    protected String[] getSurvivorNames() {
        return new String[] {"PS Survivor Space"};
    }

    @Override 
    protected String[] getMetaspaceNames() {
        return new String[] {"Metaspace"};
    }
}

SerialCollector类

public class SerialCollectorModule extends MemoryPoolModule {
    public SerialCollectorModule(List<MemoryPoolMXBean> beans) {
        super(beans);
    }

    @Override 
    protected String[] getPermNames() {
        return new String[] {"Perm Gen", "Compressed Class Space"};
    }

    @Override 
    protected String[] getCodeCacheNames() {
        return new String[] {"Code Cache"};
    }

    @Override 
    protected String[] getEdenNames() {
        return new String[] {"Eden Space"};
    }

    @Override 
    protected String[] getOldNames() {
        return new String[] {"Tenured Gen"};
    }

    @Override 
    protected String[] getSurvivorNames() {
        return new String[] {"Survivor Space"};
    }

    @Override 
    protected String[] getMetaspaceNames() {
        return new String[] {"Metaspace"};
    }
}

内存池指标获取类

public class MemoryPoolProvider {

    private MemoryPoolMetricAccessor metricAccessor;
    private List<MemoryPoolMXBean> beans;

    public MemoryPoolProvider() {
        // 创建 JVM GC 方式对应的 MemoryPoolMetricAccessor对象
        beans = ManagementFactory.getMemoryPoolMXBeans();
        for (MemoryPoolMXBean bean : beans) {
            String name = bean.getName();
            MemoryPoolMetricAccessor accessor = findByBeanName(name);
            if (accessor != null) {
                metricAccessor = accessor;
                break;
            }
        }
        if (metricAccessor == null) {
            metricAccessor = new UnknownMemoryPool();
        }
    }

    public void fetchMemoryPoolMetrics(JvmMemoryMetric memoryMetric) {
        metricAccessor.fetchMemoryPoolMetrics(memoryMetric);
    }

    private MemoryPoolMetricAccessor findByBeanName(String name) {
        if (name.indexOf("PS") > -1) { // ParallelCollector
            //Parallel (Old) collector ( -XX:+UseParallelOldGC )
            return new ParallelCollectorModule(beans);
        } else if (name.indexOf("CMS") > -1) { // CMSCollector
            // CMS collector ( -XX:+UseConcMarkSweepGC )
            return new CMSCollectorModule(beans);
        } else if (name.indexOf("G1") > -1) { // G1Collector
            // G1 collector ( -XX:+UseG1GC )
            return new G1CollectorModule(beans);
        } else if ("Survivor Space".equals(name)) { // SerialCollector
            // Serial collector ( -XX:+UseSerialGC )
            return new SerialCollectorModule(beans);
        } else {
            // Unknown
            return null;
        }
    }
}

内存回收

指标定义类

@Data
@NoArgsConstructor
public class GCMetric {

    private long fullGCCount;
    private long fullGCTime;
    private long minorGCCount;
    private long minorGCTime;
}

指标获取接口

public interface GCMetricAccessor {
    GCMetric getGCMetrics();
}

指标获取基类

public abstract class GCModule implements GCMetricAccessor {
    private GarbageCollectorMXBean[] beans;

    private volatile long lastMinorGCCount;
    private volatile long lastMinorGCTime;
    private volatile long lastFullGCCount;
    private volatile long lastFullGCTime;
    
    public GCModule(List<GarbageCollectorMXBean> beans) {
        this.beans = beans.toArray(new GarbageCollectorMXBean[0]);
    }

    @Override
    public GCMetric getGCMetrics() {
        GCMetric metrics = new GCMetric();
        for (GarbageCollectorMXBean bean : beans) {
            // 获得
            String name = bean.getName();
            if (name.equals(getNewGCName())) {
                long minorGCCount = bean.getCollectionCount();
                long minorGCTime = bean.getCollectionTime();
                metrics.setMinorGCCount(minorGCCount - this.lastMinorGCCount);
                metrics.setMinorGCTime(minorGCTime - this.lastMinorGCTime);
                this.lastMinorGCCount = minorGCCount;
                this.lastMinorGCTime = minorGCTime;
            } else if (name.equals(getOldGCName())) {
                long fullGCCount = bean.getCollectionCount();
                long fullGCTime = bean.getCollectionTime();
                metrics.setFullGCCount(fullGCCount - this.lastFullGCCount);
                metrics.setFullGCTime(fullGCTime - this.lastFullGCTime);
                this.lastFullGCCount = fullGCCount;
                this.lastFullGCTime = fullGCTime;
            } else {
                continue;
            }
        }

        return metrics;
    }

    protected abstract String getOldGCName();

    protected abstract String getNewGCName();
}

CMSGCModule类

public class CMSGCModule extends GCModule {
    public CMSGCModule(List<GarbageCollectorMXBean> beans) {
        super(beans);
    }

    @Override 
    protected String getOldGCName() {
        return "ConcurrentMarkSweep";
    }

    @Override 
    protected String getNewGCName() {
        return "ParNew";
    }
}

G1GCModule

public class G1GCModule extends GCModule {
    public G1GCModule(List<GarbageCollectorMXBean> beans) {
        super(beans);
    }

    @Override 
    protected String getOldGCName() {
        return "G1 Old Generation";
    }

    @Override 
    protected String getNewGCName() {
        return "G1 Young Generation";
    }
}

ParallelGCModule

public class ParallelGCModule extends GCModule {
    public ParallelGCModule(List<GarbageCollectorMXBean> beans) {
        super(beans);
    }

    @Override 
    protected String getOldGCName() {
        return "PS MarkSweep";
    }

    @Override 
    protected String getNewGCName() {
        return "PS Scavenge";
    }

}

SerialGCModule

public class SerialGCModule extends GCModule {
    public SerialGCModule(List<GarbageCollectorMXBean> beans) {
        super(beans);
    }

    @Override 
    protected String getOldGCName() {
        return "MarkSweepCompact";
    }

    @Override 
    protected String getNewGCName() {
        return "Copy";
    }
}

UnknowGC

public class UnknowGC implements GCMetricAccessor {
    @Override
    public GCMetric getGCMetrics() {
        return new GCMetric();
    }
}

指标获取类

public class GCProvider {

    private GCMetricAccessor metricAccessor;
    private List<GarbageCollectorMXBean> beans;

    public GCProvider() {
        // 获得 GarbageCollectorMXBean 数组。
        beans = ManagementFactory.getGarbageCollectorMXBeans();
        // 找到 GC 算法,创建对应的 GCMetricAccessor 对象。
        for (GarbageCollectorMXBean bean : beans) {
            String name = bean.getName();
            GCMetricAccessor accessor = findByBeanName(name);
            if (accessor != null) {
                metricAccessor = accessor;
                break;
            }
        }
        // 找不到 GC 算法,创建 UnknowGC 对象。
        if (metricAccessor == null) {
            this.metricAccessor = new UnknowGC();
        }
    }

    public GCMetric getGCMetrics() {
        return metricAccessor.getGCMetrics();
    }

    private GCMetricAccessor findByBeanName(String name) {
        if (name.indexOf("PS") > -1) {
            //Parallel (Old) collector ( -XX:+UseParallelOldGC )
            return new ParallelGCModule(beans);
        } else if (name.indexOf("ConcurrentMarkSweep") > -1) {
            // CMS collector ( -XX:+UseConcMarkSweepGC )
            return new CMSGCModule(beans);
        } else if (name.indexOf("G1") > -1) {
            // G1 collector ( -XX:+UseG1GC )
            return new G1GCModule(beans);
        } else if ("MarkSweepCompact".equals(name)) {
            // Serial collector ( -XX:+UseSerialGC )
            return new SerialGCModule(beans);
        } else {
            // Unknown
            return null;
        }
    }
}

各种指标获取类

@NoArgsConstructor
public class JvmMetricsFetcher {

    private Logger logger = LoggerFactory.getLogger(getClass());
    
    private static final String METRIC_NAME_APP_INSTANCE_JVM_MEM = "jvm-mem";
    private static final String METRIC_NAME_APP_INSTANCE_JVM_GC = "jvm-gc";
    
    private static final String METRIC_FIELD_NAME_FULLGCCOUNT = "fullGCCount";
    private static final String METRIC_FIELD_NAME_FULLGCTIME = "fullGCTime";
    private static final String METRIC_FIELD_NAME_MINORGCCOUNT = "minorGCCount";
    private static final String METRIC_FIELD_NAME_MINORGCTIME = "minorGCTime";
    
    private static final String METRIC_FIELD_NAME_HEAPMAX = "heapMax";
    private static final String METRIC_FIELD_NAME_HEAPUSED = "heapUsed";
    private static final String METRIC_FIELD_NAME_HEAPALLOCATED = "heapAllocated";
    private static final String METRIC_FIELD_NAME_NONHEAPMAX = "nonHeapMax";
    private static final String METRIC_FIELD_NAME_NONHEAPUSED = "nonHeapUsed";
    private static final String METRIC_FIELD_NAME_NONHEAPALLOCATED = "nonHeapAllocated";
    private static final String METRIC_FIELD_NAME_PERMGENMAX = "permGenMax";
    private static final String METRIC_FIELD_NAME_PERMGENUSED = "permGenUsed";
    private static final String METRIC_FIELD_NAME_PERMGENALLOCATED = "permGenAllocated";
    private static final String METRIC_FIELD_NAME_CODECACHEMAX = "codeCacheMax";
    private static final String METRIC_FIELD_NAME_CODECACHEUSED = "codeCacheUsed";
    private static final String METRIC_FIELD_NAME_CODECACHEALLOCATED = "codeCacheAllocated";
    private static final String METRIC_FIELD_NAME_EDENMAX = "edenMax";
    private static final String METRIC_FIELD_NAME_EDENUSED = "edenUsed";
    private static final String METRIC_FIELD_NAME_EDENALLOCATED = "edenAllocated";
    private static final String METRIC_FIELD_NAME_OLDMAX = "oldMax";
    private static final String METRIC_FIELD_NAME_OLDUSED = "oldUsed";
    private static final String METRIC_FIELD_NAME_OLDALLOCATED = "oldAllocated";
    private static final String METRIC_FIELD_NAME_SURVIVORMAX = "survivorMax";
    private static final String METRIC_FIELD_NAME_SURVIVORUSED = "survivorUsed";
    private static final String METRIC_FIELD_NAME_SURVIVORALLOCATED = "survivorAllocated";
    private static final String METRIC_FIELD_NAME_METASPACEMAX = "metaspaceMax";
    private static final String METRIC_FIELD_NAME_METASPACEUSED = "metaspaceUsed";
    private static final String METRIC_FIELD_NAME_METASPACEALLOCATED = "metaspaceAllocated";
    
    private static final String METRIC_FIELD_NAME_LOADEDCLASSES = "loadedClasses";
    private static final String METRIC_FIELD_NAME_TOTALLOADEDCLASSES = "totalLoadedClasses";
    private static final String METRIC_FIELD_NAME_UNLOADEDCLASSES = "unloadedClasses";
    
    private static final String METRIC_FIELD_NAME_TOTALTHREADS = "totalThreads";
    private static final String METRIC_FIELD_NAME_LIVINGTHREADS = "livingThreads";
    private static final String METRIC_FIELD_NAME_PEAKTHREADS = "peakThreads";
    private static final String METRIC_FIELD_NAME_DAEMONTHREAD = "daemonThread";
    
    @Value("${wdgm.monitor.jvm.metrics.fetch.intervalMS:5000}")
    private int fetchingExecutingInterval;
    @Value("${wdgm.monitor.jvm.metrics.output.intervalMS:10000}")
    private int outputingExecutingInterval;
    
    @Autowired
    private IMonitorDataOutputer metricOutputer;
    @Autowired
    private ClassLoadingProvider classLoadingProvider;
    @Autowired
    private GCProvider gcProvider;
    @Autowired
    private MemoryProvider memoryProvider;
    @Autowired
    private ThreadProvider threadProvider;
    
    private Queue<MonitorDataItem> metricCache;
    private Queue<MonitorDataItem> metricCacheBck;
    private Lock cacheOpLock = new ReentrantLock();
    
    private ScheduledExecutorService executorForFetching;
    private ScheduledExecutorService executorForOutputing;
    
    @PostConstruct
    public void init(){
        this.metricCache = new LinkedBlockingDeque<>();
        this.metricCacheBck = new LinkedBlockingDeque<>();
        
        // 启动线程
        this.executorForFetching = Executors.newScheduledThreadPool(1);
        this.executorForOutputing = Executors.newScheduledThreadPool(1);
        this.executorForFetching.scheduleAtFixedRate(new FetchingThread(), 
                5000, 
                this.fetchingExecutingInterval, 
                TimeUnit.MILLISECONDS);
        this.executorForOutputing.scheduleAtFixedRate(new OutputThread(), 
                5000, 
                this.outputingExecutingInterval, 
                TimeUnit.MILLISECONDS);
    }
    
    @PreDestroy
    public void destroy(){
        // 关闭线程
        this.executorForFetching.shutdown();
        this.executorForOutputing.shutdown();
    }
    
    class FetchingThread implements Runnable{

        @Override
        public void run() {
            try{
                // 采集JVM指标
                ClassLoadingMetric classLoadingMetrics = classLoadingProvider.getClassLoadingMetrics();
                JvmMemoryMetric jvmMemoryMetrics = memoryProvider.getJvmMemoryMetrics();
                ThreadMetric threadMetrics = threadProvider.getClassLoadingMetrics();
                MonitorDataItem jvmMetricsItem = MonitorDataItem.metricItem()
                        .withMetricName(METRIC_NAME_APP_INSTANCE_JVM_MEM)
                        .withMetricField(METRIC_FIELD_NAME_LOADEDCLASSES, classLoadingMetrics.getLoadedClasses())
                        .withMetricField(METRIC_FIELD_NAME_TOTALLOADEDCLASSES, classLoadingMetrics.getTotalLoadedClasses())
                        .withMetricField(METRIC_FIELD_NAME_UNLOADEDCLASSES, classLoadingMetrics.getUnloadedClasses())
                        
                        .withMetricField(METRIC_FIELD_NAME_CODECACHEALLOCATED, NumConvertUtil.byteToM(jvmMemoryMetrics.getCodeCacheAllocated()))
                        .withMetricField(METRIC_FIELD_NAME_CODECACHEMAX, NumConvertUtil.byteToM(jvmMemoryMetrics.getCodeCacheMax()))
                        .withMetricField(METRIC_FIELD_NAME_CODECACHEUSED, NumConvertUtil.byteToM(jvmMemoryMetrics.getCodeCacheUsed()))
                        .withMetricField(METRIC_FIELD_NAME_EDENALLOCATED, NumConvertUtil.byteToM(jvmMemoryMetrics.getEdenAllocated()))
                        .withMetricField(METRIC_FIELD_NAME_EDENMAX, NumConvertUtil.byteToM(jvmMemoryMetrics.getEdenMax()))
                        .withMetricField(METRIC_FIELD_NAME_EDENUSED, NumConvertUtil.byteToM(jvmMemoryMetrics.getEdenUsed()))
                        .withMetricField(METRIC_FIELD_NAME_HEAPALLOCATED, NumConvertUtil.byteToM(jvmMemoryMetrics.getHeapAllocated()))
                        .withMetricField(METRIC_FIELD_NAME_HEAPMAX, NumConvertUtil.byteToM(jvmMemoryMetrics.getHeapMax()))
                        .withMetricField(METRIC_FIELD_NAME_HEAPUSED, NumConvertUtil.byteToM(jvmMemoryMetrics.getHeapUsed()))
                        .withMetricField(METRIC_FIELD_NAME_METASPACEALLOCATED, NumConvertUtil.byteToM(jvmMemoryMetrics.getMetaspaceAllocated()))
                        .withMetricField(METRIC_FIELD_NAME_METASPACEMAX, NumConvertUtil.byteToM(jvmMemoryMetrics.getMetaspaceMax()))
                        .withMetricField(METRIC_FIELD_NAME_METASPACEUSED, NumConvertUtil.byteToM(jvmMemoryMetrics.getMetaspaceUsed()))
                        .withMetricField(METRIC_FIELD_NAME_NONHEAPALLOCATED, NumConvertUtil.byteToM(jvmMemoryMetrics.getNonHeapAllocated()))
                        .withMetricField(METRIC_FIELD_NAME_NONHEAPMAX, NumConvertUtil.byteToM(jvmMemoryMetrics.getNonHeapMax()))
                        .withMetricField(METRIC_FIELD_NAME_NONHEAPUSED, NumConvertUtil.byteToM(jvmMemoryMetrics.getNonHeapUsed()))
                        .withMetricField(METRIC_FIELD_NAME_OLDALLOCATED, NumConvertUtil.byteToM(jvmMemoryMetrics.getOldAllocated()))
                        .withMetricField(METRIC_FIELD_NAME_OLDMAX, NumConvertUtil.byteToM(jvmMemoryMetrics.getOldMax()))
                        .withMetricField(METRIC_FIELD_NAME_OLDUSED, NumConvertUtil.byteToM(jvmMemoryMetrics.getOldUsed()))
                        .withMetricField(METRIC_FIELD_NAME_PERMGENALLOCATED, NumConvertUtil.byteToM(jvmMemoryMetrics.getPermGenAllocated()))
                        .withMetricField(METRIC_FIELD_NAME_PERMGENMAX, NumConvertUtil.byteToM(jvmMemoryMetrics.getPermGenMax()))
                        .withMetricField(METRIC_FIELD_NAME_PERMGENUSED, NumConvertUtil.byteToM(jvmMemoryMetrics.getPermGenUsed()))
                        .withMetricField(METRIC_FIELD_NAME_SURVIVORALLOCATED, NumConvertUtil.byteToM(jvmMemoryMetrics.getSurvivorAllocated()))
                        .withMetricField(METRIC_FIELD_NAME_SURVIVORMAX, NumConvertUtil.byteToM(jvmMemoryMetrics.getSurvivorMax()))
                        .withMetricField(METRIC_FIELD_NAME_SURVIVORUSED, NumConvertUtil.byteToM(jvmMemoryMetrics.getSurvivorUsed()))
                        
                        .withMetricField(METRIC_FIELD_NAME_DAEMONTHREAD, threadMetrics.getDaemonThreads())
                        .withMetricField(METRIC_FIELD_NAME_LIVINGTHREADS, threadMetrics.getLivingThreads())
                        .withMetricField(METRIC_FIELD_NAME_PEAKTHREADS, threadMetrics.getPeakThreads())
                        .withMetricField(METRIC_FIELD_NAME_TOTALTHREADS, threadMetrics.getTotalThreads())
                        .build();
                // 采集JVM GC指标
                GCMetric gcMetrics = gcProvider.getGCMetrics();
                MonitorDataItem gcMetricsItem = MonitorDataItem.metricItem()
                        .withMetricName(METRIC_NAME_APP_INSTANCE_JVM_GC)
                        .withMetricField(METRIC_FIELD_NAME_FULLGCCOUNT, gcMetrics.getFullGCCount())
                        .withMetricField(METRIC_FIELD_NAME_FULLGCTIME, gcMetrics.getFullGCTime())
                        .withMetricField(METRIC_FIELD_NAME_MINORGCCOUNT, gcMetrics.getMinorGCCount())
                        .withMetricField(METRIC_FIELD_NAME_MINORGCTIME, gcMetrics.getMinorGCTime())
                        .build();
                
                try{
                    cacheOpLock.lock();
                    metricCache.offer(gcMetricsItem);
                    metricCache.offer(jvmMetricsItem);
                } finally{
                    cacheOpLock.unlock();
                }
            } catch(Exception e){
                logger.error("获取Jvm指标数据失败:", e);
            }
        }
        
    }
    
    class OutputThread implements Runnable{

        @Override
        public void run() {
            try{
            
                try{
                    cacheOpLock.lock();
                    
                    Queue<MonitorDataItem> q = metricCache;
                    metricCache = metricCacheBck;
                    metricCacheBck = q;
                    
                } finally{
                    cacheOpLock.unlock();
                }
                
                if(!metricCacheBck.isEmpty()){
                    List<MonitorDataItem> metricItems = new ArrayList<>();
                    for(int i = 0; i < metricCacheBck.size(); i++){
                        metricItems.add(metricCacheBck.poll());
                    }
                    metricOutputer.output(metricItems);
                }
            } catch(Exception e){
                logger.error("输出Jvm指标数据失败:", e);
            }
        }
        
    }
}

 

。。。

posted on 2020-04-27 00:28  simple_孙  阅读(1087)  评论(0编辑  收藏  举报

导航