micrometer埋點(diǎn)
本文代碼和演示基于 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ù)表的概念癌蓖。
{
"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)型包括:Counter
,Gauge
恤磷,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)出,
- 使用全局性質(zhì)的 MeterRegistry 夹攒。
- 使用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主要包括:Timer
,Counter
常空,Gauge
沽一,DistributionSummary
,除了這四個(gè)還有他們的一些細(xì)節(jié)的分支漓糙,例如LongTaskTimer
铣缠,FunctionCounter
,FunctionTimer
和TimeGauge
這些,由于這些并不是太常用下面就簡(jiǎn)單的說(shuō)一下攘残,有感興趣的可以看一下拙友,不感興趣的略過(guò)。下面逐一分析它們的作用和個(gè)人理解的實(shí)際使用場(chǎng)景歼郭。
3.5 FunctionCounter
FunctionCounter
是Counter
的特化類(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ù)序六。
? 所以要想使用埋點(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參考文章
- Spring Boot Actuator:健康檢查扔罪、審計(jì)秉沼、統(tǒng)計(jì)和監(jiān)控
- micrometer自定義metrics
- 使用 Micrometer 記錄 Java 應(yīng)用性能指標(biāo)
- 給你的SpringBoot做埋點(diǎn)監(jiān)控--JVM應(yīng)用度量框架Micrometer
- springboot2輸出metrics到influxdb
- MICROMETER application monito
- Best Java code snippets using io.micrometer.core.instrument.MeterRegistry.remove
-
meter的類(lèi)型一共有8種,本文重點(diǎn)介紹4種步势。 ?