日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Metrics —— JVM上的实时监控类库

發布時間:2025/6/15 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Metrics —— JVM上的实时监控类库 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Metrics提供了五個基本的度量類型:

  • Gauges(度量)

  • Counters(計數器)

  • Histograms(直方圖數據)

  • Meters(TPS計算器)

  • Timers(計時器)

  • Metrics中MetricRegistry是中心容器,它是程序中所有度量的容器,所有新的度量工具都要注冊到一個MetricRegistry實例中才可以使用,盡量在一個應用中保持讓這個MetricRegistry實例保持單例。

    MetricRegistry 容器

    在代碼中配置好這個MetricRegistry容器:

    @Bean public?MetricRegistry?metrics()?{????return?new?MetricRegistry(); }

    Meters TPS計算器

    TPS計算器這個名稱并不準確,Meters工具會幫助我們統計系統中某一個事件的速率。比如每秒請求數(TPS),每秒查詢數(QPS)等等。這個指標能反應系統當前的處理能力,幫助我們判斷資源是否已經不足。Meters本身是一個自增計數器。

    通過MetricRegistry可以獲得一個Meter:

    @Beanpublic?Meter?requestMeter(MetricRegistry?metrics)?{????return?metrics.meter("request"); }

    在請求中調用mark()方法,來增加計數,我們可以在不同的請求中添加不同的Meter,針對自己的系統完成定制的監控需求。

    @RequestMapping("/hello")@ResponseBodypublic?String?helloWorld()?{requestMeter.mark();????return?"Hello?World"; }

    應用運行的過程中,在console中反饋的信息:

    --?Meters?---------------------------------------------------------------------- request?????????????count?=?21055mean?rate?=?133.35?events/second1-minute?rate?=?121.66?events/second5-minute?rate?=?36.99?events/second15-minute?rate?=?13.33?events/second

    從以上信息中可以看出Meter可以為我們提供平均速率,以及采樣后的1分鐘,5分鐘,15分鐘的速率。

    Histogram 直方圖數據

    直方圖是一種非常常見的統計圖表,Metrics通過這個Histogram這個度量類型提供了一些方便實時繪制直方圖的數據

    和之前的Meter相同,我們可以通過MetricRegistry來獲得一個Histogram。

    @Beanpublic?Histogram?responseSizes(MetricRegistry?metrics)?{????return?metrics.histogram("response-sizes"); }

    在應用中,需要統計的位置調用Histogram的update()方法。

    responseSizes.update(new?Random().nextInt(10));

    比如我們需要統計某個方法的網絡流量,通過Histogram就非常的方便。

    在console中Histogram反饋的信息:

    --?Histograms?------------------------------------------------------------------ response-sizescount?=?21051min?=?0max?=?9mean?=?4.55stddev?=?2.88median?=?4.0075%?<=?7.0095%?<=?9.0098%?<=?9.0099%?<=?9.0099.9%?<=?9.00

    Histogram為我們提供了最大值,最小值和平均值等數據,利用這些數據,我們就可以開始繪制自定義的直方圖了。

    Counter 計數器

    Counter的本質就是一個AtomicLong實例,可以增加或者減少值,可以用它來統計隊列中Job的總數。

    通過MetricRegistry也可以獲得一個Counter實例。

    @Beanpublic?Counter?pendingJobs(MetricRegistry?metrics)?{????return?metrics.counter("requestCount"); }

    在需要統計數據的位置調用inc()和dec()方法。

    //?增加計數pendingJobs.inc();//?減去計數pendingJobs.dec();

    console的輸出非常簡單:

    --?Counters?--------------------------------------------------------------------requestCount?????????????count?=?21051

    只是輸出了當前度量的值。

    Timer 計時器

    Timer是一個Meter和Histogram的組合。這個度量單位可以比較方便地統計請求的速率和處理時間。對于接口中調用的延遲等信息的統計就比較方便了。如果發現一個方法的RPS(請求速率)很低,而且平均的處理時間很長,那么這個方法八成出問題了。

    同樣,通過MetricRegistry獲取一個Timer的實例:

    @Beanpublic?Timer?responses(MetricRegistry?metrics)?{????return?metrics.timer("executeTime"); }

    在需要統計信息的位置使用這樣的代碼:

    final?Timer.Context?context?=?responses.time();try?{????//?handle?request}?finally?{context.stop(); }

    console中就會實時返回這個Timer的信息:

    --?Timers?---------------------------------------------------------------------- executeTimecount?=?21061mean?rate?=?133.39?calls/second?????1-minute?rate?=?122.22?calls/second?????5-minute?rate?=?37.11?calls/second????15-minute?rate?=?13.37?calls/secondmin?=?0.00?millisecondsmax?=?0.01?millisecondsmean?=?0.00?millisecondsstddev?=?0.00?millisecondsmedian?=?0.00?milliseconds??????????????75%?<=?0.00?milliseconds??????????????95%?<=?0.00?milliseconds??????????????98%?<=?0.00?milliseconds??????????????99%?<=?0.00?milliseconds????????????99.9%?<=?0.01?milliseconds

    Gauges 度量

    除了Metrics提供的幾個度量類型,我們可以通過Gauges完成自定義的度量類型。比方說很簡單的,我們想看我們緩存里面的數據大小,就可以自己定義一個Gauges。

    metrics.register(MetricRegistry.name(ListManager.class,?"cache",?"size"),????????????????(Gauge<Integer>)?()?->?cache.size());

    這樣Metrics就會一直監控Cache的大小。

    除此之外有時候,我們需要計算自己定義的一直單位,比如消息隊列里面消費者(consumers)消費的速率生產者(producers)的生產速率的比例,這也是一個度量。

    public?class?CompareRatio?extends?RatioGauge?{????private?final?Meter?consumers;????private?final?Meter?producers;public?CacheHitRatio(Meter?consumers,?Meter?producers)?{????????this.consumers?=?consumers;????????this.producers?=?producers;}????@Overrideprotected?Ratio?getRatio()?{????????return?Ratio.of(consumers.getOneMinuteRate(),producers.getOneMinuteRate());} }

    把這個類也注冊到Metrics容器里面:

    @Beanpublic?CompareRatio?cacheHitRatio(MetricRegistry?metrics,?Meter?requestMeter,?Meter?producers)?{CompareRatio?compareRatio?=?new?CompareRatio(consumers,?producers);metrics.register("生產者消費者比率",?compareRatio);????return?cacheHitRatio; }

    Reporter 報表

    Metrics通過報表,將采集的數據展現到不同的位置,這里比如我們注冊一個ConsoleReporter到MetricRegistry中,那么console中就會打印出對應的信息。

    @Beanpublic?ConsoleReporter?consoleReporter(MetricRegistry?metrics)?{????return?ConsoleReporter.forRegistry(metrics).convertRatesTo(TimeUnit.SECONDS).convertDurationsTo(TimeUnit.MILLISECONDS).build(); }

    除此之外Metrics還支持JMX、HTTP、Slf4j等等,可以訪問?http://metrics.dropwizard.io/3.1.0/manual/core/#reporters?來查看Metrics提供的報表,如果還是不能滿足自己的業務,也可以自己繼承Metrics提供的ScheduledReporter類完成自定義的報表類。



    import java.lang.management.ManagementFactory;

    import java.net.InetSocketAddress;

    import java.util.concurrent.TimeUnit;


    import javax.annotation.PostConstruct;


    import org.slf4j.Logger;

    import org.slf4j.LoggerFactory;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

    import org.springframework.context.annotation.Bean;

    import org.springframework.context.annotation.Configuration;


    import com.codahale.metrics.JmxReporter;

    import com.codahale.metrics.MetricRegistry;

    import com.codahale.metrics.Slf4jReporter;

    import com.codahale.metrics.graphite.Graphite;

    import com.codahale.metrics.graphite.GraphiteReporter;

    import com.codahale.metrics.health.HealthCheckRegistry;

    import com.codahale.metrics.jvm.BufferPoolMetricSet;

    import com.codahale.metrics.jvm.FileDescriptorRatioGauge;

    import com.codahale.metrics.jvm.GarbageCollectorMetricSet;

    import com.codahale.metrics.jvm.MemoryUsageGaugeSet;

    import com.codahale.metrics.jvm.ThreadStatesGaugeSet;

    import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;

    import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;

    import com.zaxxer.hikari.HikariDataSource;


    import fr.ippon.spark.metrics.SparkReporter;


    @Configuration

    @EnableMetrics(proxyTargetClass = true)

    public class MetricsConfiguration extends MetricsConfigurerAdapter {


    ? ? private static final String PROP_METRIC_REG_JVM_MEMORY = "jvm.memory";

    ? ? private static final String PROP_METRIC_REG_JVM_GARBAGE = "jvm.garbage";

    ? ? private static final String PROP_METRIC_REG_JVM_THREADS = "jvm.threads";

    ? ? private static final String PROP_METRIC_REG_JVM_FILES = "jvm.files";

    ? ? private static final String PROP_METRIC_REG_JVM_BUFFERS = "jvm.buffers";


    ? ? private final Logger log = LoggerFactory.getLogger(MetricsConfiguration.class);


    ? ? private MetricRegistry metricRegistry = new MetricRegistry();


    ? ? private HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();


    ? ? @Autowired

    ? ? private JHipsterProperties jHipsterProperties;


    ? ? @Autowired(required = false)

    ? ? private HikariDataSource hikariDataSource;


    ? ? @Override

    ? ? @Bean

    ? ? public MetricRegistry getMetricRegistry() {

    ? ? ? ? return metricRegistry;

    ? ? }


    ? ? @Override

    ? ? @Bean

    ? ? public HealthCheckRegistry getHealthCheckRegistry() {

    ? ? ? ? return healthCheckRegistry;

    ? ? }


    ? ? @PostConstruct

    ? ? public void init() {

    ? ? ? ? log.debug("Registering JVM gauges");

    ? ? ? ? metricRegistry.register(PROP_METRIC_REG_JVM_MEMORY, new MemoryUsageGaugeSet());

    ? ? ? ? metricRegistry.register(PROP_METRIC_REG_JVM_GARBAGE, new GarbageCollectorMetricSet());

    ? ? ? ? metricRegistry.register(PROP_METRIC_REG_JVM_THREADS, new ThreadStatesGaugeSet());

    ? ? ? ? metricRegistry.register(PROP_METRIC_REG_JVM_FILES, new FileDescriptorRatioGauge());

    ? ? ? ? metricRegistry.register(PROP_METRIC_REG_JVM_BUFFERS, new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));

    ? ? ? ? if (hikariDataSource != null) {

    ? ? ? ? ? ? log.debug("Monitoring the datasource");

    ? ? ? ? ? ? hikariDataSource.setMetricRegistry(metricRegistry);

    ? ? ? ? }

    ? ? ? ? if (jHipsterProperties.getMetrics().getJmx().isEnabled()) {

    ? ? ? ? ? ? log.debug("Initializing Metrics JMX reporting");

    ? ? ? ? ? ? JmxReporter jmxReporter = JmxReporter.forRegistry(metricRegistry).build();

    ? ? ? ? ? ? jmxReporter.start();

    ? ? ? ? }


    ? ? ? ? if (jHipsterProperties.getMetrics().getLogs().isEnabled()) {

    ? ? ? ? ? ? log.info("Initializing Metrics Log reporting");

    ? ? ? ? ? ? final Slf4jReporter reporter = Slf4jReporter.forRegistry(metricRegistry)

    ? ? ? ? ? ? ? ? .outputTo(LoggerFactory.getLogger("metrics"))

    ? ? ? ? ? ? ? ? .convertRatesTo(TimeUnit.SECONDS)

    ? ? ? ? ? ? ? ? .convertDurationsTo(TimeUnit.MILLISECONDS)

    ? ? ? ? ? ? ? ? .build();

    ? ? ? ? ? ? reporter.start(jHipsterProperties.getMetrics().getLogs().getReportFrequency(), TimeUnit.SECONDS);

    ? ? ? ? }

    ? ? }


    ? ? @Configuration

    ? ? @ConditionalOnClass(Graphite.class)

    ? ? public static class GraphiteRegistry {


    ? ? ? ? private final Logger log = LoggerFactory.getLogger(GraphiteRegistry.class);


    ? ? ? ? @Autowired

    ? ? ? ? private MetricRegistry metricRegistry;


    ? ? ? ? @Autowired

    ? ? ? ? private JHipsterProperties jHipsterProperties;


    ? ? ? ? @PostConstruct

    ? ? ? ? private void init() {

    ? ? ? ? ? ? if (jHipsterProperties.getMetrics().getGraphite().isEnabled()) {

    ? ? ? ? ? ? ? ? log.info("Initializing Metrics Graphite reporting");

    ? ? ? ? ? ? ? ? String graphiteHost = jHipsterProperties.getMetrics().getGraphite().getHost();

    ? ? ? ? ? ? ? ? Integer graphitePort = jHipsterProperties.getMetrics().getGraphite().getPort();

    ? ? ? ? ? ? ? ? String graphitePrefix = jHipsterProperties.getMetrics().getGraphite().getPrefix();

    ? ? ? ? ? ? ? ? Graphite graphite = new Graphite(new InetSocketAddress(graphiteHost, graphitePort));

    ? ? ? ? ? ? ? ? GraphiteReporter graphiteReporter = GraphiteReporter.forRegistry(metricRegistry)

    ? ? ? ? ? ? ? ? ? ? .convertRatesTo(TimeUnit.SECONDS)

    ? ? ? ? ? ? ? ? ? ? .convertDurationsTo(TimeUnit.MILLISECONDS)

    ? ? ? ? ? ? ? ? ? ? .prefixedWith(graphitePrefix)

    ? ? ? ? ? ? ? ? ? ? .build(graphite);

    ? ? ? ? ? ? ? ? graphiteReporter.start(1, TimeUnit.MINUTES);

    ? ? ? ? ? ? }

    ? ? ? ? }

    ? ? }


    ? ? @Configuration

    ? ? @ConditionalOnClass(SparkReporter.class)

    ? ? public static class SparkRegistry {


    ? ? ? ? private final Logger log = LoggerFactory.getLogger(SparkRegistry.class);


    ? ? ? ? @Autowired

    ? ? ? ? private MetricRegistry metricRegistry;


    ? ? ? ? @Autowired

    ? ? ? ? private JHipsterProperties jHipsterProperties;


    ? ? ? ? @PostConstruct

    ? ? ? ? private void init() {

    ? ? ? ? ? ? if (jHipsterProperties.getMetrics().getSpark().isEnabled()) {

    ? ? ? ? ? ? ? ? log.info("Initializing Metrics Spark reporting");

    ? ? ? ? ? ? ? ? String sparkHost = jHipsterProperties.getMetrics().getSpark().getHost();

    ? ? ? ? ? ? ? ? Integer sparkPort = jHipsterProperties.getMetrics().getSpark().getPort();

    ? ? ? ? ? ? ? ? SparkReporter sparkReporter = SparkReporter.forRegistry(metricRegistry)

    ? ? ? ? ? ? ? ? ? ? .convertRatesTo(TimeUnit.SECONDS)

    ? ? ? ? ? ? ? ? ? ? .convertDurationsTo(TimeUnit.MILLISECONDS)

    ? ? ? ? ? ? ? ? ? ? .build(sparkHost, sparkPort);

    ? ? ? ? ? ? ? ? sparkReporter.start(1, TimeUnit.MINUTES);

    ? ? ? ? ? ? }

    ? ? ? ? }

    ? ? }


    }


    轉載于:https://blog.51cto.com/17099933344/1933119

    總結

    以上是生活随笔為你收集整理的Metrics —— JVM上的实时监控类库的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。