micrometer埋點(diǎn)(Spring boot 2.X metrics)

micrometer埋點(diǎn)


UTOOLS1578896722004.png

本文代碼和演示基于 spring boot 2.1.4.RELEASE

本文作者:gsh456,轉(zhuǎn)載請(qǐng)標(biāo)明作者或者原文鏈接燃观。


[TOC]


1前言

1.1作用

運(yùn)行良好的應(yīng)用離不開(kāi)對(duì)性能指標(biāo)的收集敢课。這些性能指標(biāo)可以有效地對(duì)生產(chǎn)系統(tǒng)的各方面行為進(jìn)行監(jiān)控,幫助運(yùn)維人員掌握系統(tǒng)運(yùn)行狀態(tài)和查找問(wèn)題原因圆仔。性能指標(biāo)監(jiān)控通常由兩個(gè)部分組成:第一個(gè)部分是性能指標(biāo)數(shù)據(jù)的收集,需要在應(yīng)用程序代碼中添加相應(yīng)的代碼來(lái)完成蔫劣;另一個(gè)部分是后臺(tái)監(jiān)控系統(tǒng)坪郭,負(fù)責(zé)對(duì)數(shù)據(jù)進(jìn)行聚合計(jì)算和提供 API 接口。在應(yīng)用中使用計(jì)數(shù)器脉幢、計(jì)量?jī)x和計(jì)時(shí)器來(lái)記錄關(guān)鍵的性能指標(biāo)歪沃。在專(zhuān)用的監(jiān)控系統(tǒng)中對(duì)性能指標(biāo)進(jìn)行匯總嗦锐,并生成相應(yīng)的圖表來(lái)進(jìn)行可視化分析。

Micrometer 為 Java 平臺(tái)上的性能數(shù)據(jù)收集提供了一個(gè)通用的 API沪曙,應(yīng)用程序只需要使用 Micrometer 的通用 API 來(lái)收集性能指標(biāo)即可奕污。Micrometer 會(huì)負(fù)責(zé)完成與不同監(jiān)控系統(tǒng)的適配工作。這就使得切換監(jiān)控系統(tǒng)變得很容易液走。Micrometer 還支持推送數(shù)據(jù)到多個(gè)不同的監(jiān)控系統(tǒng)碳默。

1.2 Actuator

你可以通過(guò)文末的參考文章獲取它的詳細(xì)概念和具體使用方法。這里只是簡(jiǎn)述下他的概念和使用方式缘眶,本文重點(diǎn)在micrometer嘱根。

Spring Boot Actuator是Spring Boot的一個(gè)組件,可以幫助你監(jiān)控和管理Spring Boot應(yīng)用巷懈,比如健康檢查该抒、審計(jì)、統(tǒng)計(jì)和HTTP追蹤等顶燕。所有的這些特性可以通過(guò)JMX或者HTTP endpoints來(lái)獲得柔逼。
你可以訪問(wèn) http://ip:端口/actuator 查看系統(tǒng)中暴露的endpoint信息,也可以加上具體的 endpoint 查看他們的詳細(xì)情況割岛,例如 http://127.0.0.1:7001/actuator/health 查看健康信息愉适。Spring Boot 2中的依賴(lài)actuator中集成的度量統(tǒng)計(jì)API使用的框架是Micrometer。官網(wǎng)

本文重點(diǎn)介紹/actuator/metrics癣漆,其他的就屬于拋磚了维咸。

1.3 metrics

打開(kāi) ip:端口/actuator/metrics 網(wǎng)址就可以看到當(dāng)前微服務(wù)的所有metrics,每一個(gè)metric都相當(dāng)于influx數(shù)據(jù)庫(kù)的一個(gè)measurement惠爽,也就是傳統(tǒng)數(shù)據(jù)庫(kù)的數(shù)據(jù)表的概念癌蓖。

UTOOLS1578886600199.png
{
    "names": [
        "jvm.memory.committed",
        "jvm.threads.states",
        "tomcat.sessions.rejected",
        "logback.events",
        "http.server.requests",
        "process.cpu.usage",
        "jvm.memory.used",
        "jvm.memory.max",
        "jvm.classes.loaded",
        "system.memory.free",
        "system.memory.used",
        "jvm.buffer.count",
        "tomcat.global.sent",
        "jvm.classes.unloaded",
        "jvm.buffer.total.capacity",
        "tomcat.sessions.active.current",
        "jvm.buffer.memory.used",
        "tomcat.sessions.alive.max",
        "jvm.gc.live.data.size",
        "tomcat.global.request.max",
        "tomcat.global.request",
        "tomcat.global.received",
        "tomcat.sessions.active.max",
        "jvm.gc.pause",
        "process.start.time",
        "tomcat.threads.config.max",
        "jvm.gc.memory.promoted",
        "timer2",
        "tomcat.global.error",
        "hystrix.rolling.max.active.threads",
        "jvm.gc.max.data.size",
        "tomcat.threads.current",
        "system.cpu.count",
        "hystrix.pool.size",
        "user.counter.total",
        "tomcat.sessions.created",
        "jvm.threads.daemon",
        "system.cpu.usage",
        "tomcat.threads.busy",
        "jvm.gc.memory.allocated",
        "system.memory.percent",
        "user.gauge.total",
        "hystrix.rolling.count.threads.rejected",
        "tomcat.sessions.expired",
        "hystrix.thread.pool",
        "jvm.threads.live",
        "jvm.threads.peak",
        "process.uptime"
    ]
}

把這些信息按照json格式化一下,這里記錄著微服務(wù)的名字婚肆,例如 process.uptime 這個(gè)metric就是記錄當(dāng)前微服務(wù)的啟動(dòng)時(shí)長(zhǎng)的metric租副,我們?cè)龠M(jìn)一步訪問(wèn)ip:端口/actuator/metrics/process.uptime 就會(huì)看到以下內(nèi)容

{
    "name": "process.uptime",
    "description": "The uptime of the Java virtual machine",
    "baseUnit": "milliseconds",
    "measurements": [
        {
            "statistic": "VALUE",
            "value": 4949999
        }
    ],
    "availableTags": [
        {
            "tag": "port",
            "values": [
                "7006"
            ]
        },
        {
            "tag": "ip",
            "values": [
                "192.168.3.70"
            ]
        },
        {
            "tag": "uuid",
            "values": [
                "192.168.3.70:7006"
            ]
        }
    ]
}

從measurements中的value值就可以看出,當(dāng)前微服務(wù)已經(jīng)運(yùn)行 1.4小時(shí)了(value實(shí)際為毫秒值這里手動(dòng)換算為小時(shí))较性,tag為標(biāo)簽用僧,標(biāo)簽是一個(gè)很重要的概念。這里有三個(gè)標(biāo)簽赞咙,分別代表當(dāng)前服務(wù)運(yùn)行的ip地址责循,端口號(hào),以及他們兩個(gè)的組合值 uuid攀操。這三個(gè)標(biāo)簽是系統(tǒng)已經(jīng)默認(rèn)有的院仿,不用管他們。你也可以自定義標(biāo)簽。

public class CustomMetrics implements MeterRegistryCustomizer<MeterRegistry> {
@Override
    public void customize(MeterRegistry registry) {
         //唯一標(biāo)識(shí), IP:port
        registry.config()
                .commonTags("ip", host + "" )
                .commonTags("port",  port+"")
                .commonTags("uuid", host + ":" + port);
    }
}

2 概念

2.1 MeterRegistry

Meter是收集關(guān)于你的應(yīng)用的一系列指標(biāo)的接口歹垫。Meter是由MeterRegistry創(chuàng)建的剥汤。每個(gè)支持的監(jiān)控系統(tǒng)都必須實(shí)現(xiàn)MeterRegistry。Micrometer中包含一個(gè)SimpleMeterRegistry排惨,它在內(nèi)存中維護(hù)每個(gè)meter的最新值秀姐,并且不支持將數(shù)據(jù)導(dǎo)出到任何地方,主要用來(lái)進(jìn)行本地開(kāi)發(fā)和測(cè)試若贮。
Micrometer 支持多個(gè)不同的監(jiān)控系統(tǒng)。通過(guò)計(jì)量器注冊(cè)表實(shí)現(xiàn)類(lèi) CompositeMeterRegistry 可以把多個(gè)計(jì)量器注冊(cè)表組合起來(lái)痒留,從而允許同時(shí)發(fā)布數(shù)據(jù)到多個(gè)監(jiān)控系統(tǒng)谴麦。對(duì)于由這個(gè)類(lèi)創(chuàng)建的計(jì)量器,它們所產(chǎn)生的數(shù)據(jù)會(huì)對(duì) CompositeMeterRegistry中包含的所有計(jì)量器注冊(cè)表都產(chǎn)生影響伸头。

2.2 常用類(lèi)型

Micrometer中匾效,Meter[1]的常用類(lèi)型包括:CounterGauge恤磷,Timer面哼,DistributionSummary ,其中前兩種用的最多扫步。

2.3 Meter命名

Micrometer中魔策,Meter的命名約定使用英文逗號(hào)(dot,也就是".")分隔單詞河胎。但是不同的監(jiān)控系統(tǒng)闯袒,對(duì)命名的規(guī)約可能并不相同,如果命名規(guī)約不一致游岳,在做監(jiān)控系統(tǒng)遷移或者切換的時(shí)候政敢,可能會(huì)對(duì)新的系統(tǒng)造成破壞。Micrometer中使用英文逗號(hào)分隔單詞的命名規(guī)則胚迫,再通過(guò)底層的命名轉(zhuǎn)換接口NamingConvention進(jìn)行轉(zhuǎn)換喷户,最終可以適配不同的監(jiān)控系統(tǒng),同時(shí)可以消除監(jiān)控系統(tǒng)不允許的特殊字符的名稱(chēng)和標(biāo)記等访锻。開(kāi)發(fā)者也可以覆蓋NamingConvention實(shí)現(xiàn)自定義的命名轉(zhuǎn)換規(guī)則:registry.config().namingConvention(myCustomNamingConvention);褪尝。在Micrometer中,對(duì)一些主流的監(jiān)控系統(tǒng)或者存儲(chǔ)系統(tǒng)的命名規(guī)則提供了默認(rèn)的轉(zhuǎn)換方式期犬。例如 在代碼中 order.request.times這些寫(xiě)恼五,那么在influxDb對(duì)應(yīng)的Measurement 就是 order_request_times,Micrometer對(duì)接不同的監(jiān)控系統(tǒng)命名規(guī)則是不一樣的哭懈。

MeterRegistry registry =  new SimpleMeterRegistry();
registry.timer("order.request.times");

2.4 Tag

Tag(標(biāo)簽)是Micrometer的一個(gè)重要的功能灾馒,嚴(yán)格來(lái)說(shuō),一個(gè)度量框架只有實(shí)現(xiàn)了標(biāo)簽的功能遣总,才能真正地多維度進(jìn)行度量數(shù)據(jù)收集睬罗。Tag的命名一般需要是有意義的轨功,所謂有意義就是可以根據(jù)Tag的命名可以推斷出它指向的數(shù)據(jù)到底代表什么維度或者什么類(lèi)型的度量指標(biāo)。假設(shè)我們需要監(jiān)控?cái)?shù)據(jù)庫(kù)的調(diào)用和Http請(qǐng)求調(diào)用統(tǒng)計(jì)容达,一般推薦的做法是:

MeterRegistry registry = new SimpleMeterRegistry();
//country相當(dāng)于 tag key古涧,China相當(dāng)于tag value,tag value不能為空
registry.counter("request.times.order", "country", "China");
registry.counter("request.times.pay", "type", "alipay");

另外Micrometer中的tag和InfluxDb的tag一致花盐,而且如果這個(gè) meter同步到influxDb羡滑,那么meter中的tag也會(huì)同步到InfluxDb 表的tag。所以tag命名要規(guī)范算芯,盡量避免 柒昏,例如剛剛的代碼就盡量不要這些寫(xiě)

registry.counter("request“,”times","order", "country", "China");
registry.counter("request","times","pay", "type", "alipay");

3. METER

3.1 Counter

Counter是一種比較簡(jiǎn)單的Meter熙揍,它是一種單值的度量類(lèi)型职祷,或者說(shuō)是一個(gè)單值計(jì)數(shù)器。Counter的作用是記錄總量或者計(jì)數(shù)值届囚,適用于一些單向增長(zhǎng)類(lèi)型的統(tǒng)計(jì)有梆,例如下單支付次數(shù)意系、接口請(qǐng)求總量記錄等等泥耀,通過(guò)Tag可以區(qū)分不同的場(chǎng)景,對(duì)于下單蛔添,可以使用不同的Tag標(biāo)記不同的業(yè)務(wù)來(lái)源或者是按日期劃分爆袍,對(duì)于Http請(qǐng)求總量記錄,可以使用Tag區(qū)分不同的URL作郭。

//標(biāo)簽值為 china的請(qǐng)求次數(shù)
MeterRegistry meterRegistry = new SimpleMeterRegistry();
//  寫(xiě)法一
Counter counter = meterRegistry.counter("request.times.order", "country", "China");
 //  寫(xiě)法二
 Counter counter2 = Counter
     .builder("request.times.order")
     .baseUnit("short") // optional
     .description("a description of what this counter does") // optional
     .tags("country", "China") // optional
     .register(registry);
//請(qǐng)求次數(shù)+1
counter.increment();
counter2.increment();
System.out.println(counter.measure()); // [Measurement{statistic='COUNT', value=1.0}]

SimpleMeterRegistry無(wú)法到數(shù)據(jù)導(dǎo)出陨囊。如果想將數(shù)據(jù)進(jìn)行導(dǎo)出,

  1. 使用全局性質(zhì)的 MeterRegistry 夹攒。
  2. 使用Metrics的靜態(tài)方法(例子中使用)蜘醋。
 private void count(String c){
        Metrics.counter("request.times.order", "country", c).increment();
    }

或者

    static final Counter userCounter = Metrics.counter("user.counter.total", "services", "demo");
    public void processCollectResult1() {
        userCounter.increment();
        System.out.println(userCounter.count());
    }
    public void processCollectResult2()  {
        userCounter.increment();
        System.out.println(userCounter.count());
    }

看情況使用,第二種在啟動(dòng)微服務(wù)后咏尝,就會(huì)metrics中存在压语,第一種只會(huì)在調(diào)用之后在metrics中存在。這兩種方式都是全局的编检,如果 名字和標(biāo)簽都是一樣的胎食,就會(huì)在上一次的基礎(chǔ)上+1;另外你也可以 在 increment() 方法中填入增加的數(shù)量允懂。

3.2 Gauge

Gauge(儀表)是獲取當(dāng)前度量記錄值的句柄厕怜,也就是它表示一個(gè)可以任意上下浮動(dòng)的單數(shù)值度量Meter。Gauge通常用于變動(dòng)的測(cè)量值,測(cè)量值用ToDoubleFunction參數(shù)的返回值設(shè)置粥航,如當(dāng)前的內(nèi)存使用情況琅捏,同時(shí)也可以測(cè)量上下移動(dòng)的”計(jì)數(shù)”,比如隊(duì)列中的消息數(shù)量递雀。官網(wǎng)文檔中提到Gauge的典型使用場(chǎng)景是用于測(cè)量集合或映射的大小或運(yùn)行狀態(tài)中的線程數(shù)柄延。Gauge一般用于監(jiān)測(cè)有自然上界的事件或者任務(wù),而Counter一般使用于無(wú)自然上界的事件或者任務(wù)的監(jiān)測(cè)缀程,所以像Http請(qǐng)求總量計(jì)數(shù)應(yīng)該使用Counter而非Gauge搜吧。

//必須在方法的外面, 我的實(shí)驗(yàn)結(jié)果是這樣的杨凑,如果又更好的方法或者不同意此觀點(diǎn)滤奈,請(qǐng)聯(lián)系我,學(xué)習(xí)是不斷進(jìn)步的蠢甲。
AtomicDouble atomicDouble = new AtomicDouble(0);
AtomicDouble ad = Metrics.gauge("user.gauge.total", init(), atomicDouble);
AtomicDouble ad2 = Metrics.gauge("user.gauge.total", init(), atomicDouble);
    public void gauge1(Double d)  {
        //這里使用  atomicDouble 或者 ad 這兩個(gè)變量都可以
        ad.set(d);
        System.out.println(atomicDouble);
    }
    public void gauge2(Double d)  {
        ad2.set(d);
        System.out.println(atomicDouble);
    }

3.3 Timer

Timer(計(jì)時(shí)器)適用于記錄耗時(shí)比較短的事件的執(zhí)行時(shí)間,通過(guò)時(shí)間分布展示事件的序列和發(fā)生頻率据忘。所有的Timer的實(shí)現(xiàn)至少記錄了發(fā)生的事件的數(shù)量和這些事件的總耗時(shí)鹦牛,從而生成一個(gè)時(shí)間序列。Timer的基本單位基于服務(wù)端的指標(biāo)而定勇吊,但是實(shí)際上我們不需要過(guò)于關(guān)注Timer的基本單位曼追,因?yàn)镸icrometer在存儲(chǔ)生成的時(shí)間序列的時(shí)候會(huì)自動(dòng)選擇適當(dāng)?shù)幕締挝弧imer接口提供的常用方法如下:

//內(nèi)存中 
public void timer1(){
        Timer timer = Timer.builder("timer")
                .tag("timer", "timersample")
                .description("timer sample test.")
                .register(new SimpleMeterRegistry());
        for(int i=0; i<2; i++) {
            timer.record(() -> {
                createOrder();
            });
        }
        System.out.println(timer.count());
        System.out.println(timer.measure());
        System.out.println(timer.totalTime(TimeUnit.SECONDS));
        System.out.println(timer.mean(TimeUnit.SECONDS));
        System.out.println(timer.max(TimeUnit.SECONDS));
    }
//全局
    public void timer2(){
        Timer timer = Metrics.timer("timer2", "timer", "timersample");
        for(int i=0; i<2; i++) {
            timer.record(() -> {
                createOrder();
            });
        }
        System.out.println(timer.count());
        System.out.println(timer.measure());
        System.out.println(timer.totalTime(TimeUnit.SECONDS));
        System.out.println(timer.mean(TimeUnit.SECONDS));
        System.out.println(timer.max(TimeUnit.SECONDS));
    }
    private static void createOrder() {
        try {
            TimeUnit.SECONDS.sleep(5); //模擬方法耗時(shí)
        } catch (InterruptedException e) {
            //no-operation
        }
    }

3.4 DistributionSummary

Summary(摘要)主要用于跟蹤事件的分布汉规,在Micrometer中礼殊,對(duì)應(yīng)的類(lèi)是DistributionSummary(分發(fā)摘要)。它的使用方式和Timer十分相似针史,但是它的記錄值并不依賴(lài)于時(shí)間單位晶伦。常見(jiàn)的使用場(chǎng)景:使用DistributionSummary測(cè)量命中服務(wù)器的請(qǐng)求的有效負(fù)載大小。

 /**
     * 只有內(nèi)存存在(actuator無(wú)法查到啄枕,influx不會(huì)自動(dòng)記錄)婚陪,用于系統(tǒng)會(huì)自動(dòng)統(tǒng)計(jì),一些最大值和平均值一些信息
     * @since JDK1.8
     * @author gsh456
     * @date 2020/1/13 10:52
     */
    public void distributionSummary1(){

        DistributionSummary summary = DistributionSummary.builder("summary")
                .tag("summary", "summarySample")
                .description("summary sample test")
                .register(new SimpleMeterRegistry());
        summary.record(2D);
        summary.record(3D);
        summary.record(4D);
        System.out.println(summary.count());
        System.out.println(summary.measure());
        System.out.println(summary.max());
        System.out.println(summary.mean());
        System.out.println(summary.totalAmount());
    }
    /**
     * 全局使用频祝,自動(dòng)記錄到influxDb泌参,同時(shí)actuator也可以查到
     * @since JDK1.8
     * @author gsh456
     * @date 2020/1/13 10:52
     */
    public void distributionSummary2(){
        DistributionSummary summary = Metrics.summary("summary2", "summary", "summarySample");
        summary.record(2D);
        summary.record(3D);
        summary.record(4D);
        System.out.println(summary.count());
        System.out.println(summary.measure());
        System.out.println(summary.max());
        System.out.println(summary.mean());
        System.out.println(summary.totalAmount());
    }

前面提到Meter主要包括:TimerCounter常空,Gauge沽一,DistributionSummary,除了這四個(gè)還有他們的一些細(xì)節(jié)的分支漓糙,例如LongTaskTimer铣缠,FunctionCounterFunctionTimerTimeGauge這些,由于這些并不是太常用下面就簡(jiǎn)單的說(shuō)一下攘残,有感興趣的可以看一下拙友,不感興趣的略過(guò)。下面逐一分析它們的作用和個(gè)人理解的實(shí)際使用場(chǎng)景歼郭。

3.5 FunctionCounter

FunctionCounterCounter的特化類(lèi)型遗契,它把計(jì)數(shù)器數(shù)值增加的動(dòng)作抽象成接口類(lèi)型ToDoubleFunction,這個(gè)接口JDK1.8中對(duì)于Function的特化類(lèi)型接口病曾。FunctionCounter的使用場(chǎng)景和Counter是一致的牍蜂,這里介紹一下它的用法:

 public static void main(String[] args) throws Exception {
            MeterRegistry registry = new SimpleMeterRegistry();
            AtomicInteger n = new AtomicInteger(0);
            //這里ToDoubleFunction匿名實(shí)現(xiàn)其實(shí)可以使用Lambda表達(dá)式簡(jiǎn)化為AtomicInteger::get
            FunctionCounter.builder("functionCounter", n, new ToDoubleFunction<AtomicInteger>() {
                @Override
                public double applyAsDouble(AtomicInteger value) {
                    return value.get();
                }
            }).baseUnit("function")
                    .description("functionCounter")
                    .tag("createOrder", "CHANNEL-A")
                    .register(registry);
            //下面模擬三次計(jì)數(shù)      
            n.incrementAndGet();
            n.incrementAndGet();
            n.incrementAndGet();
        }

3.6 FunctionTimer

FunctionTimer是Timer的特化類(lèi)型,它主要提供兩個(gè)單調(diào)遞增的函數(shù)(其實(shí)并不是單調(diào)遞增泰涂,只是在使用中一般需要隨著時(shí)間最少保持不變或者說(shuō)不減少):一個(gè)用于計(jì)數(shù)的函數(shù)和一個(gè)用于記錄總調(diào)用耗時(shí)的函數(shù)鲫竞。

3.7 LongTaskTimer

LongTaskTimer也是一種Timer的特化類(lèi)型,主要用于記錄長(zhǎng)時(shí)間執(zhí)行的任務(wù)的持續(xù)時(shí)間逼蒙,在任務(wù)完成之前从绘,被監(jiān)測(cè)的事件或者任務(wù)仍然處于運(yùn)行狀態(tài),任務(wù)完成的時(shí)候是牢,任務(wù)執(zhí)行的總耗時(shí)才會(huì)被記錄下來(lái)僵井。LongTaskTimer適合用于長(zhǎng)時(shí)間持續(xù)運(yùn)行的事件耗時(shí)的記錄,例如相對(duì)耗時(shí)的定時(shí)任務(wù)驳棱。在Spring應(yīng)用中批什,可以簡(jiǎn)單地使用@Scheduled和@Timed注解,基于spring-aop完成定時(shí)調(diào)度任務(wù)的總耗時(shí)記錄:

@Timed(value = "aws.scrape", longTask = true)
@Scheduled(fixedDelay = 360000)
void scrapeResources() {
    //這里做相對(duì)耗時(shí)的業(yè)務(wù)邏輯
}

3.8 TimeGauge

TimeGauge是Gauge的特化類(lèi)型社搅,相比Gauge驻债,它的構(gòu)建器中多了一個(gè)TimeUnit類(lèi)型的參數(shù),用于指定ToDoubleFunction入?yún)⒌幕A(chǔ)時(shí)間單位形葬。

4. 自定義metrics

上面那些都是已經(jīng)提供好的

4.1 DemoMetrics

public class DemoMetrics implements MeterBinder {
    private AtomicLong systemMemoryUsed = new AtomicLong(0);
    //這里實(shí)現(xiàn)了MeterBinder接口的bindTo方法合呐,將要采集的指標(biāo)注冊(cè)到MeterRegistry
    @Override
    public void bindTo(MeterRegistry meterRegistry) {
    //這里的MeterRegistry 是全局的
Gauge.builder("system.memory.used",systemMemoryUsed, AtomicLong::get)
//              .tag("groupName", this.groupName)
                .description("系統(tǒng)已用內(nèi)存(byte)")
                .register(registry);
}
    //定時(shí)器,定時(shí)改變內(nèi)存數(shù)值
    @Scheduled(fixedRate = 1000)
    public void recordMemory(){
         //獲取內(nèi)存信息笙以,省略
        //更改內(nèi)存
        systemMemoryUsed.set(physicalUse);
     }

4.2 注冊(cè)

@Bean
public DemoMetrics demoMetrics(){
    return new DemoMetrics();
}

4.4 驗(yàn)證

? 驗(yàn)證很簡(jiǎn)單合砂,打開(kāi) [1.3metrics網(wǎng)址](#1.3 metrics),看新的metric是否存在即可源织。

5. 與InfluxDb集成

micrometer已經(jīng)默認(rèn)集成了多種監(jiān)控系統(tǒng)翩伪,所以只需要簡(jiǎn)單的配置即可。

5.1 maven引包

        <!-- 微服務(wù)運(yùn)行監(jiān)控  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency> 
        <!-- 統(tǒng)計(jì)信息輸出到 influxdb -->
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-influx</artifactId>
        </dependency>

5.2 yml配置

# 開(kāi)放健康檢查接口
management:
   endpoints:
      web:
         exposure:
            include: "*"
   endpoint:
      health:
         show-details: ALWAYS
   metrics:
      export:
         influx:
            enabled: true
         #配置類(lèi)InfluxProperties
            #數(shù)據(jù)庫(kù)名稱(chēng)谈息,如果不填默認(rèn)為mydb
            db: mydb
            #數(shù)據(jù)庫(kù)地址
            uri: http://ip:port
            #數(shù)據(jù)庫(kù)用戶(hù)名
            userName: userName
            #密碼
            password: password
            #是否自動(dòng)建表,默認(rèn)值:true
            auto-create-db: true
            #ANY,  ONE,  QUORUM, ALL; 集群使用
            # ANY 寫(xiě)入任何一個(gè)節(jié)點(diǎn)缘屹,就返回成功(即使數(shù)據(jù)的所屬文件和節(jié)點(diǎn)不一致,也算保存成功)
            # ONE 可以寫(xiě)入任何一個(gè)節(jié)點(diǎn)侠仇,就返回成功(必須數(shù)據(jù)所屬文件和節(jié)點(diǎn)一致才算保存成功)
            # QUORUM 大多數(shù)節(jié)點(diǎn)返回成功即成功(例如 三個(gè)節(jié)點(diǎn)轻姿,兩個(gè)節(jié)點(diǎn)保存成功犁珠,即可按成功返回)
            # ALL 所有節(jié)點(diǎn)返回成功才算成功 (例如有三個(gè)節(jié)點(diǎn),所有節(jié)點(diǎn)保存成功互亮,才算是成功)
            consistency: one
            #是否啟用壓縮
            compressed: true
            #數(shù)據(jù)保留策略
            retentionPolicy: autogen
            #Time period for which Influx should retain data in the current database. For instance 7d
            # 數(shù)據(jù)保留的時(shí)間犁享,例如保留七天
            #retentionDuration:
            #How many copies of the data are stored in the cluster. Must be 1 for a single node instance.
            #節(jié)點(diǎn)的備份數(shù)據(jù),單節(jié)點(diǎn)的必須為1
            #retentionReplicationFactor:
            #每一組文件豹休,保存的時(shí)間范圍
            #retentionShardDuration:
         # 配置類(lèi)InfluxProperties的父類(lèi)StepRegistryProperties屬性
            #多長(zhǎng)時(shí)間保存一次 默認(rèn)1分鐘
            step: 1m
            #連接超時(shí)時(shí)間(如果不填默認(rèn)為1S)
            connect-timeout: 1s
            #讀取超時(shí)時(shí)間(如果不填默認(rèn)10S)
            read-timeout: 10s
            #線程數(shù)量(如果不填默認(rèn)為2)
            numThreads: 2
            #The number of parameters or columns that can be queued within each call to Exec. Defaults to 10000
            #多少條數(shù)據(jù)存到數(shù)據(jù)庫(kù)
            batchSize: 10000

只需要這兩步即可完成influxDb與metrics的集成炊昆,全局的metrics數(shù)據(jù)會(huì)根據(jù)配置文件的規(guī)則(例如一分鐘同步一次),自動(dòng)創(chuàng)建influxDb表格和數(shù)據(jù)列威根,自動(dòng)同步到InfluxDb中凤巨。另外在1.3中,我們也看到洛搀,雖然系統(tǒng)中我們 沒(méi)有配置meter敢茁,但是也會(huì)有很多的metrics,這是micrometer自動(dòng)創(chuàng)建的metric用于觀察微服務(wù)運(yùn)行的基本信息留美,像jvm使用內(nèi)存這些彰檬,這些metrics也會(huì)自動(dòng)同步到InfluxDb中去。

6. Metrics清理

? 天下文章一大抄谎砾,這個(gè)問(wèn)題困擾了我好久逢倍,終于在谷歌找到了答案,國(guó)內(nèi)文章搜索相關(guān)東西根本找不到棺榔。查詢(xún)官方文檔瓶堕,里面有metric.close()隘道。根本達(dá)不到想要的效果症歇。

? micrometer清理,metrics刪除谭梗,metric 失效 metric 有效期忘晤。

? 為何會(huì)產(chǎn)生這個(gè)問(wèn)題的主要原因是--metrics不會(huì)自動(dòng)清理,存與內(nèi)存之中激捏,同步于influxDb之外设塔,直至下次服務(wù)重啟。例如 我創(chuàng)建了 一個(gè) order.count 進(jìn)行測(cè)試远舅,metric 一分鐘同步一次闰蛔,每次同步之后自動(dòng)清零,由于metric不會(huì)消失图柏,所以同步好多為0的無(wú)效數(shù)據(jù)序六。

UTOOLS1588852383546.png

? 所以要想使用埋點(diǎn)監(jiān)控系統(tǒng),這個(gè)問(wèn)題必須解決蚤吹。

? 解決思路例诀,獲取所有metric随抠,遍歷他們,然后過(guò)濾出value為0的數(shù)據(jù)繁涂,然后讓他從MeterRegistry清理掉拱她。

@Component
@Configuration
@EnableScheduling
public class MetricCleanTimer {
    @Autowired
    MeterRegistry registry;
    //每60分鐘執(zhí)行一次
    @Scheduled(fixedDelay = 600000)
    public void clean() {
        List<Meter> meters = registry.getMeters();
        List<Meter> delete = new ArrayList<>();
        for (Meter meter : meters) {
            if (meter instanceof Counter) {
                //暫時(shí)只過(guò)濾counter的,因?yàn)閏ounter太多
                Counter counter = (Counter) meter;
                double count = counter.count();
                if (count == 0.0) {
                    //如果為0 就加入清理列表
                    delete.add(meter);
                }
            }
        }
        if (delete.size() > 0) {
            delete.forEach(e -> registry.remove(e));
        }
    }
}

7參考文章

  1. Spring Boot Actuator:健康檢查扔罪、審計(jì)秉沼、統(tǒng)計(jì)和監(jiān)控
  2. micrometer自定義metrics
  3. 使用 Micrometer 記錄 Java 應(yīng)用性能指標(biāo)
  4. 給你的SpringBoot做埋點(diǎn)監(jiān)控--JVM應(yīng)用度量框架Micrometer
  5. springboot2輸出metrics到influxdb
  6. MICROMETER application monito
  7. Best Java code snippets using io.micrometer.core.instrument.MeterRegistry.remove

  1. meter的類(lèi)型一共有8種,本文重點(diǎn)介紹4種步势。 ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末氧猬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子坏瘩,更是在濱河造成了極大的恐慌盅抚,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倔矾,死亡現(xiàn)場(chǎng)離奇詭異妄均,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)哪自,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)丰包,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人壤巷,你說(shuō)我怎么就攤上這事邑彪。” “怎么了胧华?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵寄症,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我矩动,道長(zhǎng)有巧,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任悲没,我火速辦了婚禮篮迎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘示姿。我一直安慰自己甜橱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布栈戳。 她就那樣靜靜地躺著岂傲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荧琼。 梳的紋絲不亂的頭發(fā)上譬胎,一...
    開(kāi)封第一講書(shū)人閱讀 51,679評(píng)論 1 305
  • 那天差牛,我揣著相機(jī)與錄音,去河邊找鬼堰乔。 笑死偏化,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的镐侯。 我是一名探鬼主播侦讨,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼苟翻!你這毒婦竟也來(lái)了韵卤?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤崇猫,失蹤者是張志新(化名)和其女友劉穎沈条,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體诅炉,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜡歹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涕烧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片月而。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖议纯,靈堂內(nèi)的尸體忽然破棺而出父款,到底是詐尸還是另有隱情,我是刑警寧澤瞻凤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布憨攒,位于F島的核電站,受9級(jí)特大地震影響鲫构,放射性物質(zhì)發(fā)生泄漏浓恶。R本人自食惡果不足惜玫坛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一结笨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧湿镀,春花似錦炕吸、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蒸矛,卻和暖如春瀑罗,著一層夾襖步出監(jiān)牢的瞬間胸嘴,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工斩祭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留劣像,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓摧玫,卻偏偏與公主長(zhǎng)得像耳奕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子诬像,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容