在spring1.5x使用micrometer和influxdb时,会引入micrometer-spring-legacy和micrometer-registry-influx两个包,如下maven配置,本文主要介绍下这两个包

1 Micrometer概述

主要包含计量器(Meter)和计量器的注册(MeterRegistry)组成。

  • Meter负责收集指标,每一个api都会创建一个计量器;
  • MeterRegistry用于管理计量器,并把所管理的Meter发送到监控中心,每一个监控中心对应一个MeterRegsitry,如InfluxdbMetricRegisty,是负责influxdb监控系统。micrometertor通过CompositeMeterRegistry实现了可以同时支持向多个监控中心发送指标。

Snip20200606_40

1.1 指标计量器

Timer相比其他counter等计量器多了 可以同时收集次数,耗时等指标信息,如果缺少自断,还可以进行自定义Timer

2 micrometer-registry-influx

1、作用

核心就在于提供了一个InfluxMeterRegistry。InfluxMeterRegistry作用就是定时发送指标数据到influxdb,所以如果需要修改influxdb的请求URL中sql的格式,可以修改这个类。因为它继承自MeterRegistry所以还具有组成Meter和使用Meter记录指标作用。参考之前写的InfluxdbReporter,就是发送指标数据到influxdb。

  • 注册meter,在什么时候被谁注册?在micrometre-spring-legacy的WebMvcMetricsFilter#filter中
  • 使用meter收集数据,在什么时候被谁调用?在micrometre-spring-legacy的WebMvcMetricsFilter#filter中

2、初始化InfluxMeterRegistry

在初始化时,启动一线程,该线程定时的向influxdb发送指标数据。

3 micrometer-spring-legacy

3.1 收集http request指标

提供了一个WebMvcMetricsFilter过滤器,通过这个过滤器来收集指标。流程如下:

2000418

3.1.1 Filter初始化

如何初始化这个Filter,提供了一个配置类,自动会加重MeterRegistry类型的对象,

生成Filter对象之后,spring boot就会自动加载这个Filter,不需要FilterRegistrationBean来加载。https://stackoverflow.com/questions/19825946/how-to-add-a-filter-class-in-spring-boot

Snip20200701_62

3.1.2 收集指标流程

通过WebMvcMetricsFilter的record()操作记录指标

1、WebMvcTagsProvider负责成tags

在DefaultWebMvcTagsProvider中生成uri、exception、status、method的tags。这些tags的值会组成一个标志Metert的唯一键,假设每一个唯一键对应一个Timer,此时uri、exception、status、method有多少种组合,就有多少个Meter。

在influxdb中查看tags

2、创建Timer

通过Timer#register根据Tags 来生成一个Timer。一组Tag标识一个Timer,如Influxdb中就是一个Seriries就对应一个Timer,如下对应四个Timer。

tag内容如下:

最终是通过Timer中MetricRegistry来实现,在MeterRegistry中保存了Meter集合,如下

对于Id的hash值是由name和tags的组合而成,如下

通过MeterRegistry来创建一个Timer(Timer的父类是Meter)。

3、使用Timer记录指标

如上面的“timingContext.timerSample.stop(xxx)”的stop方法

3.2 收集Tomcat指标

3.2.1 初始化

通过@Configuration来加载

3.3 保存指标

支持不同监控系统来保存指标,如Influx/Ganglie/Grahite等系统,在如下包中来通过自动化配置类来初始化对应的MeterRegtry,如对于influxdb,就是通过InfluxMetricsExportAutoConfiguration 配置类初始化InfluxMeterRegtry对象。

50483251

这里以influxdb为例

这里存在一个问题:当引入多个micrometer-registry-xx多个监控系统时,在初始化WebMetricsFilter时,注册哪一个MetrRegry???

如下代码,micrometer-spring-legacy会首先加载CompositMeterRegstry,其他监控系统的MeterRegry都会注册到CompositMeterRegestry.

3.4 收集那些指标

如查看Influxdb中收集的Micrometer指标信息,如下。

目前只介绍了Http Request和Tomcat 的监控信息,对于JVM、DataSoruce、System等信息是如何收集的??通过MeteRegistryPostProcessor来加载micrometer-core中MeterBinder的类,如下:

这个MeterRegistryPostProcessor是在如下配置类进行初始化的

MeterBinder在MeterBindersConfiguration配置类中加载

3.4.1 JVM指标

1、mircormeter自带信息

(1)JvmGcMetrics记录GC的信息

measurement 描述 指标信息
jvm_gc_pause gc总次数、累计耗时、平均耗时、最大时间 :

根据action进行分为两类GC:

1end of major GC (Full GC)

2end of minor GC (YGC)

 

 

1、字段

> select * from jvm_gc_pause limit 3;

name: jvm_gc_pause

time                action          cause                 count mean metric_type sum upper

—-                ——          —–                 —– —- ———– — —–

1591744518683000000 end of minor GC Metadata GC Threshold 1     27   histogram   27  27

1591744518687000000 end of minor GC Allocation Failure    2     41   histogram   82  49

1591744518694000000 end of major GC Metadata GC Threshold 1     141  histogram   141 141

2、tags字段

> show series from jvm_gc_pause

key

jvm_gc_pause,action=end\ of\ major\ GC,cause=Metadata\ GC\ Threshold,metric_type=histogram

jvm_gc_pause,action=end\ of\ minor\ GC,cause=Allocation\ Failure,metric_type=histogram

jvm_gc_pause,action=end\ of\ minor\ GC,cause=Metadata\ GC\ Threshold,metric_type=histogram

jvm_gc_max_data_size

老年代自服务启动之后最大值

1、字段值

> select * from jvm_gc_max_data_size limit 2;

name: jvm_gc_max_data_size

time                metric_type value

—-                ———– —–

1591744517660000000 gauge       1431830528

1591744577134000000 gauge       1431830528

2、tags

> show series from jvm_gc_max_data_size

key

jvm_gc_max_data_size,metric_type=gauge

jvm_gc_live_data_size

 full gc 的之后老年代的大小,老年代大小在变化。  1、字段

> select * from jvm_gc_live_data_size limit 1;

name: jvm_gc_live_data_size

time                metric_type value

—-                ———– —–

1591744518676000000 gauge       38198896

2、tags

> show series from jvm_gc_live_data_size

key

jvm_gc_live_data_size,metric_type=gauge

jvm_gc_memory_allocated

 两次YGC之间新生代增长大小

1、字段

> select * from jvm_gc_memory_allocated limit 1;

name: jvm_gc_memory_allocated

time                metric_type value

—-                ———– —–

1591744517659000000 counter     1273199040

2、tags

> show series from jvm_gc_memory_allocated

key

jvm_gc_memory_allocated,metric_type=counter

jvm_gc_memory_promoted

 两次fullgc之间老年生代增长大小  1、字段

> select * from jvm_gc_memory_promoted limit 1;

name: jvm_gc_memory_promoted

time                metric_type value

—-                ———– —–

1591744518697000000 counter     24576

2、tags

> show series from jvm_gc_memory_promoted

key

jvm_gc_memory_promoted,metric_type=counter

(2)jvm线程

measurement 描述 指标新

jvm_threads_daemon

守护线程

1、字段

> select * from jvm_threads_daemon limit 1;

name: jvm_threads_daemon

time                metric_type value

—-                ———– —–

1591744518673000000 gauge       30

2、tags

> show series from jvm_threads_daemon

key

jvm_threads_daemon,metric_type=gauge

jvm_threads_live 守护线程和非守护线程之和  1、字段

> select * from jvm_threads_live limit 1;

name: jvm_threads_live

time                metric_type value

—-                ———– —–

1591744518692000000 gauge       34

2、tags

> show series from jvm_threads_live

key

jvm_threads_live,metric_type=gauge

jvm_threads_peak  服务启动以来线程的最大数目。  1、字段

> select * from jvm_threads_peak limit 1;

name: jvm_threads_peak

time                metric_type value

—-                ———– —–

1591744518696000000 gauge       36

2、tags

> show series from jvm_threads_peak

key

jvm_threads_peak,metric_type=gauge

(3)JvmMemoryMetrics记录堆和buff的信息

measurement 描述 指标信息

jvm_memory_committed

used是已经被使用的内存大小,committed是当前可使用的内存大小(包括已使用的),committed >= used。committed不足时jvm向系统申请,若超过max则发生OutOfMemoryError错误 1、字段

> select * from jvm_memory_committed limit 1;

name: jvm_memory_committed

time                area    id         metric_type value

—-                —-            ———– —–

1591744517659000000 nonheap Code Cache gauge       20643840

2、tags

> show series from jvm_memory_committed

key

jvm_memory_committed,area=heap,id=PS\ Eden\ Space,metric_type=gauge

jvm_memory_committed,area=heap,id=PS\ Old\ Gen,metric_type=gauge

jvm_memory_committed,area=heap,id=PS\ Survivor\ Space,metric_type=gauge

jvm_memory_committed,area=nonheap,id=Code\ Cache,metric_type=gauge

jvm_memory_committed,area=nonheap,id=Compressed\ Class\ Space,metric_type=gauge

jvm_memory_committed,area=nonheap,id=Metaspace,metric_type=gau

jvm_memory_max

各个代的最大值。1、PS\ Eden\ Space : Eden最大值

2、PS\ Old\ Gen:老年代最大值

3、PS\ Survivor\ Space:suvivor最大值

1、字段

> select * from jvm_memory_max limit 1;

name: jvm_memory_max

time                area    id                     metric_type value

—-                —-                        ———– —–

1591744518670000000 nonheap Compressed Class Space gauge       1073741824

2、tags

> show series from jvm_memory_max

key

jvm_memory_max,area=heap,id=PS\ Eden\ Space,metric_type=gauge

jvm_memory_max,area=heap,id=PS\ Old\ Gen,metric_type=gauge

jvm_memory_max,area=heap,id=PS\ Survivor\ Space,metric_type=gauge

jvm_memory_max,area=nonheap,id=Code\ Cache,metric_type=gauge

jvm_memory_max,area=nonheap,id=Compressed\ Class\ Space,metric_type=gauge

jvm_memory_max,area=nonheap,id=Metaspace,metric_type=gauge

jvm_memory_used 各个代的占用大小

1、PS\ Eden\ Space : Eden占用大小

2、PS\ Old\ Gen:老年代占用大小

3、PS\ Survivor\ Space:suvivor占用大小

1、字段

> select * from jvm_memory_used limit 1;

name: jvm_memory_used

time                area id         metric_type value

—-                —- —         ———– —–

1591744517658000000 heap PS Old Gen gauge       38207088

2、tags

> show series from jvm_memory_used

key

jvm_memory_used,area=heap,id=PS\ Eden\ Space,metric_type=gauge

jvm_memory_used,area=heap,id=PS\ Old\ Gen,metric_type=gauge

jvm_memory_used,area=heap,id=PS\ Survivor\ Space,metric_type=gauge

jvm_memory_used,area=nonheap,id=Code\ Cache,metric_type=gauge

jvm_memory_used,area=nonheap,id=Compressed\ Class\ Space,metric_type=gauge

jvm_memory_used,area=nonheap,id=Metaspace,metric_type=gauge

jvm_buffer_count

缓存区个数

1、字段

> select * from jvm_buffer_count limit 1;

name: jvm_buffer_count

time                id     metric_type value

—-                    ———– —–

1591744518672000000 direct gauge       10

2、tags

> show series from jvm_buffer_count

key

jvm_buffer_count,id=direct,metric_type=gauge

jvm_buffer_count,id=mapped,metric_type=gauge

 jvm_buffer_total_capacity 直接缓冲区direct_capacity:直接缓冲区总大小(字节)

内存映射缓冲区mapped_capacity:内存映射缓冲区总大小(字节)

 1、tags

> select * from jvm_buffer_total_capacity limit 1;

name: jvm_buffer_total_capacity

time                id     metric_type value

—-                    ———– —–

1591744518671000000 direct gauge       81920

2、series

> show series from jvm_buffer_total_capacity

key

jvm_buffer_total_capacity,id=direct,metric_type=gauge

jvm_buffer_total_capacity,id=mapped,metric_type=gauge

jvm_buffer_memory_used

直接缓冲区direct_capacity:直接缓冲区已使用大小(字节)

内存映射缓冲区mapped_capacity:内存映射缓冲区已使用大小(字节)

1、字段

> select * from jvm_buffer_memory_used limit 1;

name: jvm_buffer_memory_used

time                id     metric_type value

—-                    ———– —–

1591744517657000000 direct gauge       81920

2、tags

> show series from jvm_buffer_memory_used

key

jvm_buffer_memory_used,id=direct,metric_type=gauge

jvm_buffer_memory_used,id=mapped,metric_type=gauge

(4)class

measurement 描述 指标信息

jvm_classes_loaded

加载类的数量

1、字段

> select * from jvm_classes_loaded limit 1;

name: jvm_classes_loaded

time                metric_type value

—-                ———– —–

1591744518693000000 gauge       10697

2、tag

> show series from jvm_classes_loaded

key

jvm_classes_loaded,metric_type=gauge

jvm_classes_unloaded

 卸载类的数量

1、字段

> select * from jvm_classes_unloaded limit 1;

name: jvm_classes_unloaded

time                metric_type value

—-                ———– —–

1591744518694000000 counter     0

2、tag

> show series from jvm_classes_unloaded

key

jvm_classes_unloaded,metric_type=counter

2、关注指标有哪些

(1)app维度

YGC次数、full gc次数、ygc时间(平均每分钟)、fullgc时间(平均每分钟)的四个IP占比的饼图,表示各个实例的占比情况,方便确认哪台机器有问题

(2)单实例

  • Ygc次数;fullgc次数;Ygc时间(平均每分钟);fullgc时间(平均每分钟);
  • 堆栈的eden、survior、old的实时占用大小和最大值;
  • jvm总线程数和守护线程数、

 

3、如何添加自定义tag,比如IP

以JvmGcMetrics类为例,在MeterBindersConfiuration.java中如下,通过@ConditionalOnMissingBean,以用户初始为准

重新在服务中通过tags初始化一个JvmGcMetrics对象:

3.5 如何定时保存指标

通过定时线程池来按固定频率发送指标,所以这个频率不能调整太小,因为如果太小比如1s,那么如果这些指标没有在1s发送完成,后续的发送就会阻塞,因为这个线程池是固定频率的。

4 应用-支持Http Request指标的扩展信息

如需要对一个Request增加IP、每一个请求的信息(错误码、耗时等)等指标信息,分为Tag字段和非Tag字段两种类型。

72388524

目前的micrometer-spring-legacy和micrometer-registry-influx是无法支持的,需要自定义开发来实现。

4.1 Tag类型

需要新增一个IP和Env信息,记录这个请求的 Ip和环境,方便后续统计,如统计流量分布情况。这些信息需要作为tag类型。

1、重写DefaultWebMvcTagsProvider类

4.2 非Tag类型

如需要新增一个url_extend字段,类型是String类型的,里面存放每一个请求的耗时、LogId、错误码等信息,例如格式可以为“耗时1_LogID1_错误码1;耗时2_LogId2_错误2″。

对于Influx的Filed类型的值,都是保存在StepTimer中,所以此时需要自定义一个StepTimer来增加这个扩展字段,如下:

在StepTimer中都是记录的StepLong的值,此时在这个自定义的Timer中需要一个String类型字段,所以参考StepLong自定义了StepString。如下:

4.3 重写InfluxMeterRetry

InfluxMeterRetry负责把指标数据输出到Influxdb,所以新增了字段,无论是tag类型或者非tag类型,都需要重写InfluxMeterRetry,来修改拼接调用influxdb的url的参数。

1、需要重写writeTimer方法来来修改拼接调用influxdb的url的参数。

上面的Filed也是需要修改的,目前Influxdb都支持long的值,如果需要支持string,还需要修改下Filed中value的类型为String类型。

2、在新增非Tag类型实现了一个Timer时,还需要重写InfluxMeterRestry中

4.3 重新定义WebMvcMetricsFilter

如何指定使用自定义MvcTagsProvider类或者自定义InfluxMeterRegestry?此时需要实现一个WebMvcMetricsFilter,这是为了替换如下WebMvcTagsProvider类

5 mirometer版本roadmap

https://github.com/micrometer-metrics/micrometer/releases

6 参考

1、使用 Micrometer 记录 Java 应用性能指标https://www.ibm.com/developerworks/cn/java/j-using-micrometer-to-record-java-metric/index.html

2、jvm监控-阿里云:https://www.alibabacloud.com/help/zh/doc-detail/70073.htm

 

(全文完)

分类&标签