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);
            }
        }
        
    }
}

 

。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM