目录

Kubernetes集群的监控告警

在实际生产环境中,一般不会用直接运行容器的方式部署,主流方式是用Prometheus Operator来部署监控告警系统。Prometheus Operator是CoreOS公司开发的增强Prometheus在Kubernetes集群中能力的开源项目。利用K8S的CRD特性简化了使用,并且实现了自动化Reload等特性。

Prometheus-Operator 部署和配置

helm
manifest

Operator CRD 的使用

Prometheus监控Java SpringBoot应用

集成SpringBoot Actuator

以当前主流的SpringBoot为例,讲解一下SpringBoot Actuator如何集成Prometheus。Actuator是SpringBoot自带的应用监控管理组件,可以通过RESTful API请求来监管、审计、收集应用的运行情况,配合SpringBoot Admin可以实现一整套对微服务的监控管理。启用Actuator只需要添加一个依赖:

“org.springframework.boot:spring-boot-starter-actuator”

而集成Prometheus客户端就是添加另一个依赖:

“io.micrometer:micrometer-registry-prometheus”

这个jar实现了自定义的actuator endpoint(/actuator/prometheus),部署后在Prometheus Server上添加静态配置或自动发现规则,即可监控到服务端点,刮取/actuator/prometheus下的Metrics数据。

Actuator里面有很多非常敏感的API,比如/threaddump /heapdump /shutdown,一般在非本地环境都会配置关闭,比如只启用这几个,并且在入口做IP或者URL的访问限制。

1
2
3
4
5
management:
endpoints:
web:
exposure:
include: "info,health,prometheus"

Grafana可以使用 JVM Micrometer(4701), Spring Boot Statistics(6756) 这两个Dashboard。

:另一个常用的Java应用集成方式是在JVM启动时指定开启JMX,搭配JMX Exporter收集JVM监控数据,虽然可靠性更佳,但扩展性不如actuator,建议在传统非SpringBoot基础上的Java服务上使用。

利用Micrometer自定义监控指标

SpringBoot Actuator使用的是Micrometer,Micrometer之于Prometheus Client相当于Slf4J之于Log4j / Logback, 也就是说Micrometer与Slf4J一样,提供了一套监控Facade不关心真正的实现的MetricsRegistry。因此自定义监控,我们调用Micrometer的API即可,真正的实现类在micrometer-registry-prometheus,它会自己做适配处理,即使不用Prometheus,换一个Registry即可。

Spring官方博客有关于这方面的介绍:https://spring.io/blog/2018/03/16/micrometer-spring-boot-2-s-new-application-metrics-collector

因此只要通过Micrometer即可做到监控指标与具体实现分离,下面是一个例子:

1
todo

https://www.cnblogs.com/duanxz/p/10179946.html
http://throwable.coding.me/2018/11/17/jvm-micrometer-prometheus/

Prometheus监控NodeJS服务

集成prom-client

ECMAScript表示:我们不学Java界搞花里胡哨的针对接口编程、过度封装,要接入Prometheus直接3行代码搞定!

1
todo

这里用到的prom-client是一个第三方的开源实现,读完源码感觉代码质量很高,不过一开始担心有很多对象keys遍历的操作精确的纳秒时间获取会不会性能不高,后来用最简单的输出HelloWorld的HTTP接口对比压测之后发现性能影响在5%以内,可以放心使用。再后来突然想明白,代码用process.hrtime()而不是Date.now()是有深意的, 因为NodeJS中Date.now()/new Date()并不一定是准确时间,而process.hrtime()可以获取机器最准确的精确到纳秒的时间,虽然性能与Date.now()差了一个数量级,但这对监控Method执行时间是必要的!

Grafana可以直接使用我开发的Dashboard: https://grafana.com/grafana/dashboards/11159

NodeJS中自定义监控指标

以koa2 + TypeScript为例,下面这些代码自定义了3个自定义指标:

todo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { collectDefaultMetrics, register, Counter, Gauge, Summary } from 'prom-client';

// 初始化监控指标
const labelNames = ['application', 'url'];

const total = new Counter({
name: 'total_req',
help: 'total request number',
labelNames
});
const lastDuration = new Gauge({
name: 'last_duration',
help: 'the last duration or response time of last request',
labelNames
});
const avgLatency = new Summary({
name: 'avg_latency',
help: 'average latency of processing incoming requests',
percentiles: [0.01, 0.1, 0.5, 0.9, 0.99],
maxAgeSeconds: 600,
labelNames
});

// 在业务代码中触发监控数据变化,传入的是动态的Tag/Label
function trigger (appName, routeName, url) {
total.labels(appName, routeName, url).inc(1, timestamp);
lastDuration.labels(appName, routeName, url).set(cost, timestamp);
avgLatency.labels(appName, routeName, url).observe(cost);
}

// 收集NodeJS运行时的默认开启的监控指标,并添加一个 /metrics 的API访问
const metricsInterval = collectDefaultMetrics({
timeout: 5000
});
router.get('/metrics', ctx => {
ctx.headers['content-type'] = register.contentType;
ctx.body = register.metrics();
});

运行效果如下,访问 /metrics 可以获得3个自定义指标 + N个默认指标,包括了CPU,堆内存详情,Event Loop延迟等等非常有用的指标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# HELP total_req total request number
total_req{application="_demo",route="get-user.yaml",path="/user/:userId"} 2 1564310684635

# HELP last_duration the last duration or response time of last request
last_duration{application="_demo",route="get-user.yaml",path="/user/:userId"} 456 1564310684635

# HELP avg_latency average latency of processing incoming requests
avg_latency{quantile="0.01",application="_demo",route="get-user.yaml",path="/user/:userId"} 456
avg_latency{quantile="0.1",application="_demo",route="get-user.yaml",path="/user/:userId"} 456
avg_latency{quantile="0.5",application="_demo",route="get-user.yaml",path="/user/:userId"} 602
avg_latency{quantile="0.9",application="_demo",route="get-user.yaml",path="/user/:userId"} 748
avg_latency{quantile="0.99",application="_demo",route="get-user.yaml",path="/user/:userId"} 748
avg_latency_sum{application="_demo",route="get-user.yaml",path="/user/:userId"} 1204
avg_latency_count{application="_demo",route="get-user.yaml",path="/user/:userId"} 2

process_cpu_user_seconds_total 0.515 1564310692789

process_cpu_system_seconds_total 0.062 1564310692789
process_cpu_seconds_total 0.5770000000000001 1564310692789
process_start_time_seconds 1564310423
process_resident_memory_bytes 181211136 1564310692789

nodejs_eventloop_lag_seconds 0.000122892 1564310692789
nodejs_active_handles_total 3 1564310692789
nodejs_active_requests_total 0 1564310692789

... 此处省略N个默认监控指标

nodejs_version_info{version="v10.5.0",major="10",minor="5",patch="0"} 1

Prometheus监控Golang服务

集成client_golang库

Prometheus官方提供了Golang的Client Library(https://github.com/prometheus/client_golang),毕竟Prometheus本身也是Golang写的,集成方式也非常简单。

1
todo

Grafana可以使用 Golang Go Processes(6671) 这个Dashboard

Golang应用自定义监控指标

1
todo