Metrics主要提供对应用程序各种关键指标的度量手段和报告方式,因度量方式科学合理,源码扩展性强,被广泛应用到各大框架中,如Kafka、Apache Storm、Spring Cloud等。要实现应用程序的性能监控,可以考虑如下方式:1、实时更新监控数据并写入数据库,对数据库有性能压力且业务与性能监控产生耦合;2、将监控数据写入日志,应用最广泛,无侵入;3、采用JMX方式监控性能数据,数据要封装,借助JMX客户端可远程访问;4、提供嵌入式的RESTful接口;5、借助Metrics工具集。
Metrics提供了强大的数据收集方式,并且在Metrics内部集成了CSV、JMX、Log、Console四大Reporter,Reporter是一个非常容易扩展的接口,使用者可以通过自定义Reporter形式将Metrics收集到的数据展示(存储)在任何地方。Metrics是一个jar包,可以通过POM的方式引入:
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>3.2.6</version>
</dependency>
1、五大Metric详解
Metrics包含三大组件,分别是Reporter、Metric、MetricRegistry。首先在应用程序中植入Metric用于收集系统运行时产生的性能数据,各个Metric被注册在MetricRegistry中,Reporter从MetricRegistry中获取各个Metric的数据,然后进行输出或者存储等操作。Metrics提供了五大可用组件。
Meter主要用于测量一组事件发生的速率。 Meter的代码示例:
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
public class MeterExample {
private final static MetricRegistry registry=new MetricRegistry();
private final static Meter requestMeter=registry.meter("tps");
private final static Meter sizeMeter=registry.meter("volume");
public static void main(String[] args) {
ConsoleReporter reporter=ConsoleReporter.forRegistry(registry)
.convertRatesTo(TimeUnit.MINUTES)
.convertDurationsTo(TimeUnit.MINUTES)
.build();
reporter.start(10, TimeUnit.SECONDS);
for(int i=0;i<30;i++) {
upload(new byte[ThreadLocalRandom.current().nextInt(1000)]);
randomSleep();
}
}
private static void upload(byte[] request) {
requestMeter.mark();
sizeMeter.mark(request.length);
}
private static void randomSleep() {
try {
TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果节选:
2023/9/17 09:45:12 =============================================================
-- Meters ----------------------------------------------------------------------
tps
count = 9
mean rate = 13.46 events/minute
1-minute rate = 12.68 events/minute
5-minute rate = 12.19 events/minute
15-minute rate = 12.07 events/minute
volume
count = 3574
mean rate = 5346.03 events/minute
1-minute rate = 2756.62 events/minute
5-minute rate = 727.83 events/minute
15-minute rate = 291.15 events/minute
2023/9/17 09:45:22 =============================================================
-- Meters ----------------------------------------------------------------------
tps
count = 10
mean rate = 11.97 events/minute
1-minute rate = 11.69 events/minute
5-minute rate = 11.98 events/minute
15-minute rate = 12.00 events/minute
volume
count = 3721
mean rate = 4455.34 events/minute
1-minute rate = 2474.47 events/minute
5-minute rate = 733.12 events/minute
15-minute rate = 297.71 events/minute
Gauge是最简单的Metric类型,它只返回一个Value值。它可以用来查询某个关键队列在某个时刻的size,或者用来查看当前网站的在线人数等。它在实际应用中的应用的比较广泛。
JMX Attribute Gauge可以用于追踪远程JVM的运行指标。
Ration Gauge可以用于两个数字间的某种比率,如业务受理成功率等。
Cached Gauge对实时性要求不高,可以将监测的数据暂时缓存一段时间,等设置时间过期后再重新获取。
Derivative Gauge允许从某个Gauge value中获取特定的属性和值。
Counter Metric提供了一个64位数字的递增和递减的解决方案,可以帮助我们解决在度量的过程中性能侵入的问题。
直方图(Histogram)也称位质量分布图,是一种统计报告图,由一些列高度不等的纵向条纹或线段表示数据分布的情况。Metrics提供了Histogram的数据统计方式。传统计算中间值的方式是将所有数据都放到一个数据集合中,然后对其进行排序整理,最后采取折半方式获取其中一个值,就认为其是中间值。这种计算方式需要数据集合记录所有数据,导致应用程序中存放大量的数据,容易内存溢出。有四种解决方案:1、Uniform Reservoirs采用随机的抽样来度量数据,然后存放在一个数据集合中进行中间值的统计,这种算法称为Vitter R算法。这种方式非常适合统计长时间运行的度量数据,因为它是采用随机抽样的方式位数据集合。2、Exponentially Decaying Reservoris(指数衰变)的方式既是Metrics的默认方式,也是官网推荐的,建议在平时工作中使用这种方式即可。Exponentially Decaying Reservoirs通过一个正向衰减优先级列表来实现,该列表用于更新维护数据的指数权重,使得需要计算中间值的数据集合维持在一个特定的数量区间中,然后对其进行中值运算。3、Sliding Window Reservoirs(滑动窗口)的原理非常简单,主要在该窗口中存放最近的一定数量的值进行median(中间值)的计算。4、Sliding Time Window Reservoirs(时间滑动窗口),主要是根据指定的、最近的时间范围内的数据进行median(中间值)的计算。
Timer是基于Histogram和Meter的一种针对度量数据进行统计方式,主要用于统计业务方法的响应速度,即调用某个业务接口共花费了多少时间。
2、Reporter详解
Metrics内置了4种输出度量报告的形式,当然也可以自定义报告的形式。
ConsoleReporter,用于将Metric度量数据进行控制台输出,这种Reporter形式适用于开发阶段。在构造ConsoleReporter的时候,采用其静态方法forRegistery()进行构造。forRegistry后会返回一个Builder对象,该对象提供很多用于控制信息的输出方式和方法参数。convertRatesTo,指定时间单位进行输出,只有在Meter和Timer会用到Rate的时间单位设置。convertDurationsTo,以设定的时间单位进行输出。start方法是启动报告,以多长时间输出一次。
LogReporter是生产环境常用的一种方式。使用过程如下:引入log依赖;配置log appender; 在应用程序中创建Reporter对象时,将输出导向配置的logger。
JMXReporter,内部不提供定时线程服务,在对其进行start后,无需给定任何时间间隔及时间单位,JMXReporter更多的操作其实是将Metric Registry中所有Metric定义成MBean,并且注册到ObjectNameFactory中。统计结果需要在JMX客户端中查看。
CsvReporter与logger reporter比较类似,因为CSV文件不同于日志可以通过配置的方式处理,需要在创建CsvReporter时,显式指定一个存在的目录,以存放Reporter输出的CSV文件,如果该目录不存在则会出现错误。
3、Metrics插件
Health Check的使用步骤:1、引入依赖关系metrics-healthchecks;2、引入检查项依赖的插件,如死锁检查需要引入metrics-jvm依赖;3、在程序代码中先将关注的healthcheck子类检查内容注册到HealthCheckRegistry中,然后将Health Check所有子类的运行结果作为一个Gauge注册到Metric Registry中。
自定义Health Check的步骤如下:1、定义新检查项,继承HealthCheck;2、在程序使用时,将新检查项注册到HealthCheckRegistry;3、将HealthCheckRegistry注册到Metrics Registry中作为一个Gauge项。多个HealthCheck都是参照这个步骤中的第二步,都注册到HealthCheckRegistry中。
JVM Instrumentation插件,提供了大量针对JVM的相关度量信息,所有的Metric都是以Metric Set的形式出现。