关键词:Prometheus; Grafana; Alertmanager; SpringBoot; SpringBoot Actuator; 监控; 告警;
在前一篇Spring Boot Actuator 模块 详解:健康检查,度量,指标收集和监控中,咱们学习了 Spring Boot Actuator 模块的做用、配置和重要端点的介绍。java
我也提到了,我主要目的是想要给咱们项目的微服务应用都加上监控告警。Spring Boot Actuator的引入只是第一步,在本章中,我会介绍:git
Prometheus 中文名称为普罗米修斯,受启发于Google 的Brogmon 监控系统,从2012年开始由前Google工程师在Soundcloud 以开源软件的形式进行研发,2016年6月发布1.0版本。Prometheus 能够看做是 Google 内部监控系统Borgmon 的一个实现。github
下图说明了Prometheus 的体系结构及其部分生态系统组件。其中 Alertmanager 用于告警,Grafana 用于监控数据可视化,会在文章后面继续提到。正则表达式
在这里咱们了解到Prometheus 这几个特征便可:spring
详细了解请阅读 Prometheus 官方文档
Grafana 是一款采用 go 语言编写的开源应用,容许您从Elasticsearch,Prometheus,Graphite,InfluxDB等各类数据源中获取数据,并经过精美的图形将其可视化。docker
除了Prometheus的AlertManager 能够发送报警,Grafana 同时也支持告警。Grafana 能够无缝定义告警在数据中的位置,可视化的定义阈值,并能够经过钉钉、email等平台获取告警通知。最重要的是可直观的定义告警规则,不断的评估并发送通知。shell
因为Grafana alert告警比较弱,大部分告警都是经过Prometheus Alertmanager进行告警.
请注意Prometheus仪表板也具备简单的图形。 可是Grafana的图形化要好得多。数据库
延伸阅读:tomcat
Prometheus 监控平台中除了负责采集数据和存储,还能定制事件规则,可是这些事件规则要实现告警通知的话须要配合Alertmanager 组件来完成。springboot
AlertManager 支持告警分组(将多个告警合并一块儿发送)、告警抑制以及告警静默(同一个时间段内不发出重复的告警)功能。
延伸阅读: 官网对Alertmanager的介绍
目前,监控系统采集指标有两种方式,一种是『推』,另外一种就是『拉』:
推的表明有 ElasticSearch,InfluxDB,OpenTSDB 等,须要你从程序中将指标使用 TCP,UDP 等方式推送至相关监控应用,只是使用 TCP 的话,一旦监控应用挂掉或存在瓶颈,容易对应用自己产生影响,而使用 UDP 的话,虽然不用担忧监控应用,可是容易丢数据。
拉的表明,主要表明就是 Prometheus,让咱们不用担忧监控应用自己的状态。并且能够利用 DNS-SRV 或者 Consul 等服务发现功能就能够自动添加监控。
Prometheus 监控应用的方式很是简单,只须要进程暴露了一个用于获取当前监控样本数据的 HTTP 访问地址。这样的一个程序称为Exporter,Exporter 的实例称为一个 Target 。Prometheus 经过轮训的方式定时从这些 Target 中获取监控数据样本,对于应用来说,只须要暴露一个包含监控数据的 HTTP 访问地址便可,固然提供的数据须要知足必定的格式,这个格式就是 Metrics 格式.
metric name>{<label name>=<label value>, ...}
主要分为三个部分
各个部分需符合相关的正则表达式
a-zA-Z_:*
_[a-zA-Z0-9_]*
须要注意的是,label value 最好使用枚举值,而不要使用无限制的值,好比用户 ID,Email 等,否则会消耗大量内存,也不符合指标采集的意义。
前面简述了Prometheus 监控的原理。那么咱们的Spring Boot 应用怎么提供这样一个 HTTP 访问地址,提供的数据还得符合上述的 Metrics 格式 ?
还记得吗,在Spring Boot Actuator 模块 详解:健康检查,度量,指标收集和监控中,我有提到过Actuator 模块也能够和一些外部的应用监控系统整合,其中就包括Prometheus 。那么Spring Boot Actuator 怎么让 Spring Boot 应用和Prometheus 这种监控系统结合起来呢?
这个桥梁就是[MicroMeter]()。Micrometer 为 Java 平台上的性能数据收集提供了一个通用的 API,应用程序只须要使用 Micrometer 的通用 API 来收集性能指标便可。Micrometer 会负责完成与不一样监控系统的适配工做。
接下去咱们一边结合实际的Demo,一边讲解说明。
初始的Demo项目建立请参照 Spring Boot Actuator 模块 详解:健康检查,度量,指标收集和监控
实操部分会将分为两个部分,本部分主要是将应用如何集成Prometheus 和 Grafana 完成指标收集和可视化。
为了让Spring Boot 应用和Prometheus 集成,你须要增长micrometer-registry-prometheus
依赖。
<!-- Micrometer Prometheus registry --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency>
添加上述依赖项以后,Spring Boot 将会自动配置 PrometheusMeterRegistry
和 CollectorRegistry
来以Prometheus 能够抓取的格式(即上文提到的 Metrics 格式)收集和导出指标数据。
全部的相关数据,都会在Actuator 的 /prometheus
端点暴露出来。Prometheus 能够抓取该端点以按期获取度量标准数据。
/prometheus
端点咱们仍是以咱们以前的Demo项目为例子。深究一下这个端点的内容。添加micrometer-registry-prometheus
依赖后,咱们访问http://localhost:8080/actuator/prometheus
地址,能够看到一下内容:
# HELP jvm_buffer_total_capacity_bytes An estimate of the total capacity of the buffers in this pool # TYPE jvm_buffer_total_capacity_bytes gauge jvm_buffer_total_capacity_bytes{id="direct",} 90112.0 jvm_buffer_total_capacity_bytes{id="mapped",} 0.0 # HELP tomcat_sessions_expired_sessions_total # TYPE tomcat_sessions_expired_sessions_total counter tomcat_sessions_expired_sessions_total 0.0 # HELP jvm_classes_unloaded_classes_total The total number of classes unloaded since the Java virtual machine has started execution # TYPE jvm_classes_unloaded_classes_total counter jvm_classes_unloaded_classes_total 1.0 # HELP jvm_buffer_count_buffers An estimate of the number of buffers in the pool # TYPE jvm_buffer_count_buffers gauge jvm_buffer_count_buffers{id="direct",} 11.0 jvm_buffer_count_buffers{id="mapped",} 0.0 # HELP system_cpu_usage The "recent cpu usage" for the whole system # TYPE system_cpu_usage gauge system_cpu_usage 0.0939447637893599 # HELP jvm_gc_max_data_size_bytes Max size of old generation memory pool # TYPE jvm_gc_max_data_size_bytes gauge jvm_gc_max_data_size_bytes 2.841116672E9 # 此处省略超多字...
能够看到,这些都是按照上文提到的 Metrics 格式组织起来的程序监控指标数据。
metric name>{<label name>=<label value>, ...}
安装请参阅官方文档。内容很少可是很细致。你能够选择二进制安装或者是docker 的方式。这里不赘述。
接下去,咱们须要配置Prometheus 去收集咱们 Demo 项目/actuator/prometheus
的指标数据。
# my global config global: scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. # scrape_timeout is set to the global default (10s). # Load rules once and periodically evaluate them according to the global 'evaluation_interval'. rule_files: # - "first_rules.yml" # - "second_rules.yml" # A scrape configuration containing exactly one endpoint to scrape: # Here it's Prometheus itself. scrape_configs: # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. - job_name: 'prometheus' # metrics_path defaults to '/metrics' # scheme defaults to 'http'. static_configs: - targets: ['localhost:9090'] # demo job - job_name: 'springboot-actuator-prometheus-test' # job name metrics_path: '/actuator/prometheus' # 指标获取路径 scrape_interval: 5s # 间隔 basic_auth: # Spring Security basic auth username: 'actuator' password: 'actuator' static_configs: - targets: ['10.60.45.113:8080'] # 实例的地址,默认的协议是http
重点请关注这里的配置:
# demo job - job_name: 'springboot-actuator-prometheus-test' # job name metrics_path: '/actuator/prometheus' # 指标获取路径 scrape_interval: 5s # 间隔 basic_auth: # Spring Security basic auth username: 'actuator' password: 'actuator' static_configs: - targets: ['10.60.45.113:8080'] # 实例的地址,默认的协议是http
配置完成以后,咱们启动Prometheus 测试一下,若是你是docker 方式的话,在prometheus.yml
文件所在目录执行以下命令,便可启动Prometheus:
docker run -d -p 9090:9090 \ -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \ prom/prometheus --config.file=/etc/prometheus/prometheus.yml
http://ip:9090
,可看到以下界面:Insert metric at cursor
,便可选择监控指标;点击 Graph
,便可让指标以图表方式展现;点击Execute
按钮,便可看到相似下图的结果:你也能够在输入框中输入PromQL来进行更高级的查询。PromQL是Prometheus 的自定义查询语言,经过PromQL用户能够很是方便地对监控样本数据进行统计分析。
curl -X POST http://ip:9090/-/reload
能够看到,Prometheus 自带的监控面板很是“简陋”。因此引入Grafana 来实现更友好、更贴近生产的监控可视化。
$ docker run -d --name=grafana -p 3000:3000 grafana/grafana
访问 http://ip:3000/login
,初始帐号/密码为:admin/admin
,第一次登陆会让你修改密码。
Configuration
中Add Data Source
,会看到以下界面:Save & Test
:+
按钮,并点击Dashboard,将会看到相似以下的界面:Add Query
,便可看到相似以下的界面:在Metrics
处输入要查询的指标,指标的取值详见Spring Boot应用的 /actuator/prometheus
端点,例如jvm_memory_used_bytes
、jvm_threads_states_threads
、jvm_threads_live_threads
等,Grafana会给你较好的提示,而且能够用PromQL
实现较为复杂的计算,例如聚合、求和、平均等。若是想要绘制多个线条,可点击Add Query
按钮,
Visualization
,能够选择可视化的类型和一些相关的配置。这里就很少赘述,留给读者本身探索。General
进行基础配置,不赘述:到这里,我想聪明的读者们应该已经学会如何去可视化一个指标数据了。可是应该不少人都会以为,若是有好多指标的话,配置起来其实是蛮繁琐的。
是否有开箱即用、通用型的DashBoard模板呢?
前往 Grafana Lab - Dashboards ,输入关键词便可搜索指定Dashboard。你就能够得到你想要的😎😎。
另外,这些已有的dashboard也可让咱们更快掌握一些panel的配置和dashboard的使用。
这里直接给出两款我以为比较好用的dashboard:
这一款我须要提一下,刚开始我引入的时候是无效的,不知道读者会不会遇到和我同样的问题,若是遇到了,请到dashboard的设置里面,修改 variables 中 $application
和$instance
两个变量的Definition
。
还有我我的是推荐,在这两款dashboard上面作一些定制化操做,或者说把二者的panel结合起来。
Import
按钮:Import
按钮:在实操部分二,主要讲如何自定义监控指标(好比咱们的一些业务数据,这也叫作埋点)和如何使用Alertmanager完成监控告警。
模拟需求:有一个订单服务,监控 [实时订单金额]、[10分钟内下单失败率]
PrometheusCustomMonitor
这里面咱们自定义了三个metrics:
requests_error_total
: 下单失败次数order_request_count
:下单总次数order_amount_sum
:下单金额统计@Component public class PrometheusCustomMonitor { /** * 记录请求出错次数 */ private Counter requestErrorCount; /** * 订单发起次数 */ private Counter orderCount; /** * 金额统计 */ private DistributionSummary amountSum; private final MeterRegistry registry; @Autowired public PrometheusCustomMonitor(MeterRegistry registry) { this.registry = registry; } @PostConstruct private void init() { requestErrorCount = registry.counter("requests_error_total", "status", "error"); orderCount = registry.counter("order_request_count", "order", "test-svc"); amountSum = registry.summary("order_amount_sum", "orderAmount", "test-svc"); } public Counter getRequestErrorCount() { return requestErrorCount; } public Counter getOrderCount() { return orderCount; } public DistributionSummary getAmountSum() { return amountSum; } }
/order
接口当 flag="1"
时,抛异常,模拟下单失败状况。在接口中统计order_request_count
和order_amount_sum
。
@RestController public class TestController { @Resource private PrometheusCustomMonitor monitor; //.... @RequestMapping("/order") public String order(@RequestParam(defaultValue = "0") String flag) throws Exception { // 统计下单次数 monitor.getOrderCount().increment(); if ("1".equals(flag)) { throw new Exception("出错啦"); } Random random = new Random(); int amount = random.nextInt(100); // 统计金额 monitor.getAmountSum().record(amount); return "下单成功, 金额: " + amount; } }
PS:实际项目中,采集业务监控数据的时候,建议使用AOP的方式记录,不要侵入业务代码。不要像我Demo中这样写。
GlobalExceptionHandler
统计下单失败次数requests_error_total
:
@ControllerAdvice public class GlobalExceptionHandler { @Resource private PrometheusCustomMonitor monitor; @ResponseBody @ExceptionHandler(value = Exception.class) public String handle(Exception e) { monitor.getRequestErrorCount().increment(); return "error, message: " + e.getMessage(); } }
启动项目,访问http://localhost:8080/order
和http://localhost:8080/order?flag=1
模拟下单成功和失败的状况,而后咱们访问http://localhost:8080/actuator/prometheus
,能够看到咱们自定义指标已经被/prometheus
端点暴露出来了:
# HELP requests_error_total # TYPE requests_error_total counter requests_error_total{application="springboot-actuator-prometheus-test",status="error",} 41.0 # HELP order_request_count_total # TYPE order_request_count_total counter order_request_count_total{application="springboot-actuator-prometheus-test",order="test-svc",} 94.0 # HELP order_amount_sum # TYPE order_amount_sum summary order_amount_sum_count{application="springboot-actuator-prometheus-test",orderAmount="test-svc",} 53.0 order_amount_sum_sum{application="springboot-actuator-prometheus-test",orderAmount="test-svc",} 2701.0
这里我新增一个dashboard做为演示用,一些步骤前面讲过这里就直接省略:
sum(rate(requests_error_total{application="springboot-actuator-prometheus-test"}[10m])) / sum(rate(order_request_count_total{application="springboot-actuator-prometheus-test"}[10m])) * 100
模拟告警规则:
- 服务是否下线
- 10分钟内下单失败率是否大于10%
这里采用二进制包的方式部署。
# 全局配置 global: resolve_timeout: 5m smtp_smarthost: 'xxxxxx' smtp_from: 'xxxx@xx.com' smtp_auth_username: 'xxxx@xx.com' smtp_auth_password: 'XXXXXX' # 路由配置 route: receiver: 'default-receiver' # 父节点 group_by: ['alertname'] # 分组规则 group_wait: 10s # 为了可以一次性收集和发送更多的相关信息时,能够经过group_wait参数设置等待时间 group_interval: 1m #定义相同的Group之间发送告警通知的时间间隔 repeat_interval: 1m routes: # 子路由,根据match路由 - receiver: 'rhf-mail-receiver' group_wait: 10s match: # 匹配自定义标签 team: rhf # 告警接收者配置 receivers: - name: 'default-receiver' email_configs: - to: 'xxxx@xx.com' - name: 'rhf-mail-receiver' email_configs: - to: 'xxxx@xx.com'
目前官方内置的第三方通知集成包括:邮件、 即时通信软件(如Slack、Hipchat)、移动应用消息推送(如Pushover)和自动化运维工具(例如:Pagerduty、Opsgenie、Victorops)。Alertmanager的通知方式中还能够支持Webhook,经过这种方式开发者能够实现更多个性化的扩展支持(钉钉、企业微信等)。
相关配置延伸阅读:
Alermanager会将数据保存到本地中,默认的存储路径为data/
。所以,在启动Alertmanager以前须要建立相应的目录:
./alertmanager
用户也在启动Alertmanager时使用参数修改相关配置。--config.file
用于指定alertmanager配置文件路径,--storage.path
用于指定数据存储路径。
9093
端口:Alert
菜单下能够查看Alertmanager 接收到的告警内容。Silences
菜单下则能够经过UI建立静默规则。Status
菜单下面能够看到Alertmanager 的配置信息。
curl -X POST http://ip:9093/-/reload
在Prometheus 目录下新建test-svc-alert-rule.yaml
来设置告警规则,内容以下:
groups: - name: svc-alert-rule rules: - alert: svc-down # 服务是否下线 expr: sum(up{job="springboot-actuator-prometheus-test"}) == 0 for: 1m labels: # 自定义标签 severity: critical team: rhf # 咱们小组的名字,对应上面match 的标签匹配 annotations: summary: "订单服务已下线,请检查!!" - alert: order-error-rate-high # 10分钟内下单失败率是否大于10% expr: sum(rate(requests_error_total{application="springboot-actuator-prometheus-test"}[10m])) / sum(rate(order_request_count_total{application="springboot-actuator-prometheus-test"}[10m])) > 0.1 for: 1m labels: severity: major team: rhf annotations: summary: "订单服务响应异常!!" description: "10分钟订单错误率已经超过10% (当前值: {{ $value }} !!!"
实际项目中,能够用一个rule
目录存放全部的告警规则,而后rule/*.yaml
的方式配置
在 prometheus.yml
文件下,引用test-svc-alert-rule.yaml
告警规则配置,并开启 Alertmanager。
alerting: alertmanagers: - static_configs: - targets: # alertmanage default start port 9093 - localhost:9093 rule_files: - /data/prometheus-stack/prometheus/rule/*.yml
如今咱们配置完成以后,热加载一下Prometheus 的配置。而后尝试触发告警条件。
http://ip:9093
界面能够看到触发的告警到这里咱们的Spring Boot 微服务监控告警模块也就算讲述完毕了。但愿能给你带来一些收获。
对应的源码能够Github上看到。
若是本文有帮助到你,但愿能点个赞,这是对个人最大动力🤝🤝🤗🤗。