史上最全:prometheus+alertmanager 实现监控预警

文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 :

免费赠送 :《尼恩Java面试宝典》 持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备
免费赠送 :《尼恩技术圣经+高并发系列PDF》 ,帮你 实现技术自由,完成职业升级, 薪酬猛涨!加尼恩免费领
免费赠送 经典图书:《Java高并发核心编程(卷1)加强版》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
免费赠送 经典图书:《Java高并发核心编程(卷2)加强版》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
免费赠送 经典图书:《Java高并发核心编程(卷3)加强版》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领

免费赠送 资源宝库: Java 必备 百度网盘资源大合集 价值>10000元 加尼恩领取


史上最全:prometheus+alertmanager 实现监控预警

尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要监控预警类的面试题:

怎么做 指标的治理?

怎么做监控预警?

很多很多小伙伴遇到这样的难题,但是没有实操过,也了解不全面,导致丢了一些很好的机会。

尼恩结合自己的《10WqpsNetty网关实操操作》,给大家梳理 一本配套的《Prometheus圣经》,帮助大家一招制敌。

同时,把这个指标监控预警相关面试题, 也收入咱们的 《尼恩Java面试宝典PDF》V175版本《架构专题》,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》《Prometheus圣经》的PDF,请到文末公号【技术自由圈】获取

Prometheus圣经的上下两部分

  • prometheus学习圣经Part1:使用prometheus+Grafana实现指标监控

  • prometheus学习圣经Part2:使用prometheus+Alertmanager实现指标预警

在这里插入图片描述

完整的PDF,请在 技术自由圈 公众号获取。

在这里插入图片描述

1. prometheus学习圣经(下):使用prometheus+alertmanager 实现指标预警

监控和告警,是孪生兄弟,监控就需要报警,没有报警的监控是不完善的。

那么prometheus生态,报警究竟是怎么实现呢,告警组件它又是怎么和prometheus一起协调,并且完成报警的发送呢?

先来看一下, prometheus的官方生态架构图

在这里插入图片描述

prometheus可以抓取exporter中暴露出来的指标数据并且存储,prometheus有自己的查询语句PromQL,

grafana面板中的显示的都是PromQL查询prometheus时序数据库出来的数据。

和grafana一样,告警组件alertmanager也是依靠prometheus的PromQL,具体的流程大致是:在prometheus中可以定义一些PromQL语句,当语句查询出来的值超过预定的阈值,prometheus发送报警给alertmanager了,

alertmanager负责把prometheus发送过去的相关的报警指标分类,并且执行报警(微信,邮件,企微)

Prometheus的架构中被划分为两个部分,

  1. 在Prometheus Server中定义告警规则,以及产生告警,

  2. Alertmanager组件则用于处理这些由Prometheus产生的告警。

    Alertmanager即Prometheus体系中告警的统一处理中心。Alertmanager提供了多种内置第三方告警通知方式,同时还提供了对Webhook通知的支持,通过Webhook用户可以完成对告警更多个性化的扩展。

prometheus触发一条告警的过程:
prometheus—>触发阈值—>超出持续时间—>alertmanager—>分组|抑制|静默—>媒体类型—>邮件|钉钉|微信等。

在这里插入图片描述

在这里插入图片描述

Alertmanager: 从 Prometheus server 端接收到 alerts 后,会进行去重,分组,并路由到相应的接收方,发出报警,常见的接收方式有:电子邮件,微信,钉钉, slack等。

在Prometheus中一条告警规则主要由以下几部分组成

  1. 告警名称:用户需要为告警规则命名,当然对于命名而言,需要能够直接表达出该告警的主要内容
  2. 告警规则:告警规则实际上主要由PromQL进行定义,其实际意义是当表达式(PromQL)查询结果持续多长时间(During)后出发告警

2.自定义告警规则

Prometheus中的告警规则允许你基于PromQL表达式定义告警触发条件,Prometheus后端对这些触发规则进行周期性计算,当满足触发条件后则会触发告警通知。

默认情况下,用户可以通过Prometheus的Web界面查看这些告警规则以及告警的触发状态。

当Promthues与Alertmanager关联之后,可以将告警发送到外部服务如Alertmanager中并通过Alertmanager可以对这些告警进行进一步的处理。

prometheus 告警规则的案例

先来一个简单点的案例

groups:
- name: example
  rules:
  - alert: HighErrorRate
    expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5
    for: 10m
    labels:
      severity: page
    annotations:
      summary: High request latency
      description: description info


下面是尼恩用来做直接内存阈告警的例子:

groups:
# 报警组组名称
- name: DirectMemoryAlert
  #报警组规则
  rules:
   #告警名称,需唯一
  - alert: DirectMemoryAlert
    #promQL表达式
    expr:  gateway_direct_memory  > 5
    #满足此表达式持续时间超过for规定的时间才会触发此报警
    for: 1m
    labels:
      #严重级别
      severity: page
    annotations:
     #发出的告警标题
      summary: "实例 {{ $labels.instance }} 直接内存使用超过 5M"
      #发出的告警内容
      description: "实例{{ $labels.instance }} 直接内存使用超过 5M, (当前值为: {{ $value }})M"

可以将一组相关的规则设置定义在一个group下。 在每一个group中定义多个告警规则(rule)。

告警规则主要由以下几部分组成

  • alert:告警规则的名称。
  • expr:基于PromQL表达式告警触发条件,用于计算是否有时间序列满足该条件。
  • for:评估等待时间,可选参数。用于表示只有当触发条件持续一段时间后才发送告警。在等待期间新产生告警的状态为pending。
  • labels:自定义标签,允许用户指定要附加到告警上的一组附加标签。
  • annotations:用于指定一组附加信息,比如用于描述告警详细信息的文字等,annotations的内容在告警产生时会一同作为参数发送到Alertmanager。

让Prometheus启用定义的告警规则

在Prometheus全局配置文件中,通过 rule_files 指定一组告警规则文件的访问路径,路径下存放告警规则文件

Prometheus启动后会自动扫描这些路径下告警规则文件中定义的内容,并且根据这些规则计算是否向外部发送通知:

rule_files:
  [ - <filepath_glob> ... ]

默认情况下, Prometheus会每分钟对这些告警规则进行计算,注意周期是 每分钟。

如果用户想 自定义的告警计算周期 ,则可以通过evaluation_interval来覆盖默认的计算周期:

global:
  [ evaluation_interval: <duration> | default = 1m ]

prometheus告警规则文件的模板化

在告警规则文件的annotations中,有两个重要的、关于规则的描述信息项目:

  • summary:描述告警的概要信息,
  • description: 描述告警的详细信息。

除了Prometheus之外,同时Alertmanager的UI也会根据这两个标签值,显示告警信息。

为了提升可读性,Prometheus支持模板化label和annotations的中标签的值,通过表达式去访问。

比如,通过下面两个表达式,可以访问数据序列中的 标签和样本值:

  • $labels.变量 ,这个表达式可以访问当前告警实例中指定标签的值。

  • $value ,这个表达式则可以获取当前PromQL表达式计算的样本值。

# To insert a firing element's label values:
{{ $labels.<labelname> }}
# To insert the numeric expression value of the firing element:
{{ $value }}


举个例子,以通过模板化优化summary以及description的内容的可读性

- alert: KubeAPILatencyHigh
  annotations:
    message: The API server has a 99th percentile latency of {{ $value }} seconds
      for {{ $labels.verb }} {{ $labels.resource }}.
  expr: |
    cluster_quantile:apiserver_request_latencies:histogram_quantile{job="apiserver",quantile="0.99",subresource!="log"} > 4
  for: 10m
  labels:
    severity: critical

这条警报的大致含义是,假如 kube-apiserver 的 P99 响应时间大于 4 秒,并持续 10 分钟以上,就产生报警。

首先要注意的是由 for 指定的 Pending Duration (持续时间)。

这个 for 参数主要用于降噪,很多类似响应时间这样的指标都是有抖动的,通过指定 Pending Duration,我们可以 过滤掉这些瞬时抖动,让 on-call 人员能够把注意力放在真正有持续影响的问题上。

那么显然,下面这样的状况是不会触发这条警报规则的,因为虽然指标已经达到了警报阈值,但持续时间并不够长:

查看告警规则和状态

可以通过Prometheus WEB界面中的Alerts菜单查,看当前Prometheus下的所有告警规则,以及其当前所处的活动状态。

在这里插入图片描述状态说明Prometheus Alert 告警状态有三种状态:Inactive、Pending、Firing。

  • 1、Inactive:非活动状态,表示正在监控,但是还未有任何警报触发。
  • 2、Pending:表示这个警报必须被触发。由于警报可以被分组、压抑/抑制或静默/静音,所
    以警报等待验证,一旦所有的验证都通过,则将转到Firing 状态。
  • 3、Firing:将警报发送到AlertManager,它将按照配置将警报的发送给所有接收者。一旦警
    报解除,则将状态转到Inactive,如此循环。

表示这个警报必须被触发。 警报等待验证,告警触发条件满足,但 for 定义的持续时间不满足。

在这里插入图片描述

Firing:将警报发送到AlertManager,它将按照配置将警报的发送给所有接收者。

在这里插入图片描述

对于已经pending或者firing的告警,Prometheus也会将它们存储到时间序列ALERTS{}中。 可以通过表达式,查询告警实例:

ALERTS{alertname="<alert name>", alertstate="pending|firing", <additional alert labels>}

样本值为1表示当前告警处于活动状态(pending或者firing),当告警从活动状态转换为非活动状态时,样本值则为0。

Prometheus fire 之后

Prometheus fire 之后 将警报发送到AlertManager,

在这里插入图片描述

AlertManager 将按照配置将警报的发送给所有接收者。

尼恩的直接内存告警案例中, 接受者是一个 webhook,收到告警的时候,断点被命中。

在这里插入图片描述

回顾一下:prometheus配置基础规则

prometheus.yml 属性配置

属性 描述
scrape_interval 样本采集周期,默认为1分钟采集一次
evaluation_interval 告警规则计算周期,默认为1分钟计算一次
rule_files 指定告警规则的文件
scrape_configs job的配置项,里面可配多组job任务
job_name 任务名称,需要唯一性
static_configs job_name的配置选项,一般使用file_sd_configs 热加载配置
file_sd_configs job_name的动态配置选项,使用此配置可以实现配置文件的热加载
files: file_sd_configs配置的服务发现的文件路径列表,支持.json,.yml或.yaml,路径最后一层支持通配符*
refresh_interval file_sd_configs中的files重新加载的周期,默认5分钟

下面是一个完整的参考案例:

# my global config
global:
  scrape_interval:     15s # 采样周期
  evaluation_interval: 15s # 告警规则计算周期

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - alertmanager:9093

# 报警规则文件可以指定多个,并且可以使用通配符*
rule_files:
  - "rules/*_rules.yml"
  # - "second_rules.yml"

# 采集job配置
scrape_configs:
  - job_name: 'prometheus'
    #使用file_sd_configs热加载配置文件
    file_sd_configs:
      #指定1分钟加载一次配置
    - refresh_interval: 1m
      files:
      - config_prometheus.json
  
  - job_name: 'linux_base'
    file_sd_configs:
    - refresh_interval: 1m
      files:
      - config_exporter.json
      
  - job_name: 'service_base'
    file_sd_configs:
    - refresh_interval: 1m
      files:
      - config_mtail.json
      
  - job_name: 'grafana'
    file_sd_configs:
    - refresh_interval: 1m
      files:
      - config_grafana.json



此处我们使用rule_files属性来设置告警文件,这里设置报警规则,rules/host_rules.yml

groups:
# 报警组组名称
- name: hostStatsAlert
  #报警组规则
  rules:
   #告警名称,需唯一
  - alert: hostCpuUsageAlert
    #promQL表达式
    expr: sum(avg without (cpu)(irate(node_cpu_seconds_total{mode!='idle'}[5m]))) by (instance) > 0.85
    #满足此表达式持续时间超过for规定的时间才会触发此报警
    for: 1m
    labels:
      #严重级别
      severity: page
    annotations:
     #发出的告警标题
      summary: "实例 {{ $labels.instance }} CPU 使用率过高"
      #发出的告警内容
      description: "实例{{ $labels.instance }} CPU 使用率超过 85% (当前值为: {{ $value }})"
  - alert: hostMemUsageAlert
    expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes)/node_memory_MemTotal_bytes > 0.85
    for: 1m
    labels:
      severity: page
    annotations:
      summary: "实例 {{ $labels.instance }} 内存使用率过高"
      description: "实例 {{ $labels.instance }} 内存使用率 85% (当前值为: {{ $value }})"

下面是尼恩用来做直接内存阈值监控的例子 directmemory_rules.yml

groups:
# 报警组组名称
- name: DirectMemoryAlert
  #报警组规则
  rules:
   #告警名称,需唯一
  - alert: DirectMemoryAlert
    #promQL表达式
    expr:  gateway_direct_memory  > 5
    #满足此表达式持续时间超过for规定的时间才会触发此报警
    for: 1m
    labels:
      #严重级别
      severity: page
    annotations:
     #发出的告警标题
      summary: "实例 {{ $labels.instance }} 直接内存使用超过 5M"
      #发出的告警内容
      description: "实例{{ $labels.instance }} 直接内存使用超过 5M, (当前值为: {{ $value }})M"

3. Alertmanager 的警报管理能力:

  • Prometheus负责中配置警报规则,将警报发送到Alertmanager 。
  • Alertmanager 负责管理这些警报,包括沉默,抑制,合并和发送通知 。

Alertmanager 发送通知有多种方式,其内部集成了邮箱、Slack、企业微信、webhook等方式,

网上也有大量例子实现对第三方软件的集成,如钉钉等。

本文介绍邮件报警方式和通过使用java来搭建webhook自定义通知报警的方式。

3.1 Alertmanager的特性

Alertmanager除了提供基本的告警通知能力以外,还主要提供了如:分组、抑制以及静默等告警特性
在这里插入图片描述

3.2告警的分组

分组(group): 将类似性质的警报合并为单个通知。

在某些情况下,比如由于系统宕机导致大量的告警被同时触发,在这种情况下分组机制可以将这些被触发的告警合并为一个告警通知.

告警的分组 避免一次性接受大量的告警通知,而无法对问题进行快速定位。

例如,当集群中有数百个正在运行的服务实例,并且为每一个实例设置了告警规则。

假如此时发生了网络故障,可能导致大量的服务实例无法连接到数据库,结果就会有数百个告警被发送到Alertmanager。

而作为用户,可能只希望能够在一个通知中就能查看哪些服务实例收到影响。

这时可以按照服务所在集群或者告警名称对告警进行分组,而将这些告警内聚在一起成为一个通知。

告警分组,告警时间,以及告警的接受方式可以通过Alertmanager的配置文件进行配置。

3.3告警的抑制

抑制(inhibition): 当警报发出后,停止重复发送由此警报引发的其他警报,即合并一个故障引起的多个报警事件,可以 消除冗余告警

例如,当集群不可访问时触发了一次告警,通过配置Alertmanager可以忽略与该集群有关的其它所有告警。这样可以避免接收到大量与实际问题无关的告警通知。

抑制机制同样通过Alertmanager的配置文件进行设置。

3.3告警的静默

静默(silences): 是一种简单的特定时间静音的机制,

例如:服务器要升级维护可以先设置这个时间段告警静默。

静默提供了一个简单的机制, 可以快速根据标签对告警进行静默处理。

如果接收到的告警符合静默的配置,Alertmanager则不会发送告警通知。

静默设置需要在Alertmanager的Werb页面上进行设置。

4.alertmanager配置及部署

4.1.alertmanager配置

alertmanager会定义一个基于标签匹配规则的路由树,用以接收到报警后根据不同的标签匹配不同的路由,来将报警发送给不同的receiver。

global:
  resolve_timeout: 5m

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 1m
  repeat_interval: 4h
  receiver: 'webhook'
receivers:
- name: 'webhook'
  webhook_configs:
    - url: 'http://192.168.56.1:28088/alert-demo/hook/demo'	

如果只是定义一个路由route,则这个路由需要接收并处理所有的报警,

如果需要区分不同的报警发送给不同的receiver,则需要配置多个子级route来处理不同的报警,而根route此时必须能够接收处理所有的报警。

下面是来自于互联网的其他小伙伴的,一个多个子级route来处理不同的报警的例子

#根路由
route:
  #顶级路由配置的接收者(匹配不到子级路由,会使用根路由发送报警)
  receiver: 'default-receiver'
  #设置等待时间,在此等待时间内如果接收到多个报警,则会合并成一个通知发送给receiver
  group_wait: 30s
  #两次报警通知的时间间隔,如:5m,表示发送报警通知后,如果5分钟内再次接收到报警则不会发送通知
  group_interval: 5m
  #发送相同告警的时间间隔,如:4h,表示4小时内不会发送相同的报警
  repeat_interval: 4h
  #分组规则,如果满足group_by中包含的标签,则这些报警会合并为一个通知发给receiver
  group_by: [cluster, alertname]
  routes:
  #子路由的接收者
  - receiver: 'database-pager'
    group_wait: 10s
    #默认为false。false:配置到满足条件的子节点点后直接返回,true:匹配到子节点后还会继续遍历后续子节点
    continue:false
    #正则匹配,验证当前标签service的值是否满足当前正则的条件
    match_re:
      service: mysql|cassandra
  #子路由的接收者
  - receiver: 'frontend-pager'
    group_by: [product, environment]
    #字符串匹配,匹配当前标签team的值为frontend的报警
    match:
      team: frontend

#定义所有接收者
receivers:
#接收者名称
- name: 'default-receiver'
  #接收者为webhook类型
  webhook_configs:
  #webhook的接收地址
  - url: 'http://127.0.0.1:5001/'
- name: 'database-pager'
  webhook_configs:
  - url: 'http://127.0.0.1:5002/'
- name: 'frontend-pager'
  webhook_configs:
  - url: 'http://127.0.0.1:5003/'

4.2.alertmanager部署

使用尼恩的一键部署脚本,就可以了

version: "3.5"
services:
  prometheus:
    image: prom/prometheus:v2.30.0
    container_name: prometheus
    volumes:
     - /tmp:/tmp
     - ./prometheus.yml:/etc/prometheus/prometheus.yml
     - ./rules:/rules
    command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus --storage.tsdb.wal-compression --storage.tsdb.retention.time=7d"
    hostname: prometheus
    environment:
      TZ: "Asia/Shanghai"
    ports:
      - "9090:9090"
    networks:
       base-env-network:
         aliases:
          - prometheus

  alertmanager:
    image: prom/alertmanager:v0.23.0
  #		restart: always
    container_name: alertmanager
    hostname: alertmanager
    environment:
      TZ: "Asia/Shanghai"
    ports:
    - 9093:9093
    command:
      - "--config.file=/etc/alertmanager/alertmanager.yml"
      - "--log.level=debug"
    volumes:
    - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
    - ./alertmanager:/alertmanager


其中涉及到直接内存的告警配置, 修改alertmanager.yml,内容如下:

global:
  resolve_timeout: 5m

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 1m
  repeat_interval: 4h
  receiver: 'webhook'
receivers:
- name: 'webhook'
  webhook_configs:
    - url: 'http://192.168.56.1:28088/alert-demo/hook/demo'	


启动后访问 http://cdh1:9093/ 查看alertmanager 是否启动成功,

可以通过 status 按钮,查看alertmanager及其配置:

http://cdh1:9093/#/alerts

在这里插入图片描述

4.3prometheus关联alertmanager

prometheus.yml中的alerting标签下配置上alertmanager的地址即可,配置如下:

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['192.168.199.23:9093']

添加后重启prometheus即可。

报警通知方式的配置

通知方式一:邮箱报警

一个简单的 来自互联网的demo,大致如下:

global:
  #超时时间
  resolve_timeout: 5m
  #smtp地址需要加端口
  smtp_smarthost: 'smtp.126.com:25'
  smtp_from: '[email protected]'
  #发件人邮箱账号
  smtp_auth_username: '[email protected]'
  #账号对应的授权码(不是密码),阿里云个人版邮箱目前好像没有授权码,126邮箱授权码可以在“设置”里面找到
  smtp_auth_password: '1qaz2wsx'
  smtp_require_tls: false

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 1m
  repeat_interval: 4h
  receiver: 'mail'
receivers:
- name: 'mail'
  email_configs:
  - to: '[email protected]'

设置后如果有通知,即可收到邮件如下:
在这里插入图片描述

先来看一下alertmanager的配置文件结构

global:
  smtp_smarthost: 'smtp.qq.com:465'
  smtp_from: '[email protected]'
  smtp_auth_username: '[email protected]'
  smtp_auth_password: 'xxxxxxxxx'
  smtp_require_tls: false
route:
  group_by: [alertname]
  group_wait: 5s
  group_interval: 5m
  repeat_interval: 5s
  receiver: default-receiver
receivers:
- name: 'default-receiver'
  email_configs:
  - to: '[email protected]'

通知方式二:使用webhook(java)回调发短信


global:
  resolve_timeout: 5m

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 1m
  repeat_interval: 4h
  receiver: 'webhook'
receivers:
- name: 'webhook'
  webhook_configs:
    - url: 'http://192.168.56.1:28088/alert-demo/hook/demo'	

使用webhook方式,alertmanager调用webhook钩子地址,发送post请求,

Post请求参数为json字符串(字符串类型):

{
  "receiver": "webhook",
  "status": "firing",
  "alerts": [
    {
      "status": "firing",
      "labels": {
        "alertname": "DirectMemoryAlert",
        "application": "api-gateway",
        "instance": "192.168.56.1:8888",
        "job": "api-gateway",
        "monitor": "Netty直接内存监控",
        "severity": "page",
        "tip": "根据实际情况调整",
        "version": "1.0.0"
      },
      "annotations": {
        "description": "实例192.168.56.1:8888 直接内存使用超过 5M, (当前值为: 288)M",
        "summary": "实例 192.168.56.1:8888 直接内存使用超过 5M"
      },
      "startsAt": "2024-03-11T05:51:22.939Z",
      "endsAt": "0001-01-01T00:00:00Z",
      "generatorURL": "http://prometheus:9090/graph?g0.expr=gateway_direct_memory+%3E+5\u0026g0.tab=1",
      "fingerprint": "2e3375fead9bb5fe"
    }
  ],
  "groupLabels": {
    "alertname": "DirectMemoryAlert"
  },
  "commonLabels": {
    "alertname": "DirectMemoryAlert",
    "application": "api-gateway",
    "instance": "192.168.56.1:8888",
    "job": "api-gateway",
    "monitor": "Netty直接内存监控",
    "severity": "page",
    "tip": "根据实际情况调整",
    "version": "1.0.0"
  },
  "commonAnnotations": {
    "description": "实例192.168.56.1:8888 直接内存使用超过 5M, (当前值为: 288)M",
    "summary": "实例 192.168.56.1:8888 直接内存使用超过 5M"
  },
  "externalURL": "http://alertmanager:9093",
  "version": "4",
  "groupKey": "{}:{alertname=\"DirectMemoryAlert\"}",
  "truncatedAlerts": 0
}

此时需要使用java(其他任何语言都可以,反正只要能处理http的请求就行)搭建个http的请求处理器来处理报警通知,如下:

package com.crazymaker.cloud.alertmanager.demo.controller;

import com.crazymaker.springcloud.common.util.JsonUtil;
import com.crazymaker.springcloud.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@RestController
@RequestMapping("/hook")
@Slf4j
public class AlertManagerDemoController {


    public static final Map<String, Object> ALERT_FAIL = new HashMap<>();
    public static final Map<String, Object> ALERT_SUCCESS = new HashMap<>();

    static {
        ALERT_FAIL.put("msg", "报警失败");
        ALERT_FAIL.put("code", 0);
        ALERT_SUCCESS.put("msg", "报警成功");
        ALERT_SUCCESS.put("code", 1);
    }


    @RequestMapping(value = "/demo", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String pstn(@RequestBody String json) {
        log.debug("alert notify  params: {}", json);

        if (StringUtils.isBlank(json)) {
            return JsonUtil.pojoToJson(ALERT_FAIL);//告警发送失败
        }
        Map<String, Object> jo = JsonUtil.jsonToMap(json);

        //获取 标签
        Map<String, Object> annotations = (Map<String, Object>) jo.get("commonAnnotations");

        if (annotations == null) {
            return JsonUtil.pojoToJson(ALERT_FAIL);//告警发送失败
        }


        Object status = jo.get("status");
        Object subject = annotations.get("summary");
        Object content = annotations.get("description");
        log.error("status: {}", status);
        log.error("summary: {}", subject);
        log.error("content: {}", content);

        //开发发送短信
        List<String> users = getRelatedPerson();

        try {
            boolean success = sendMsg(subject, content, users);
            if (success) {
                return JsonUtil.pojoToJson(ALERT_SUCCESS);//告警发送成功
            }
        } catch (Exception e) {
            log.error("=alert sms notify error. json={}", json, e);
        }
        return JsonUtil.pojoToJson(ALERT_FAIL);//告警发送失败

    }
    //todo  发送短信

    private boolean sendMsg(Object subject, Object content, List<String> users) {
        return true;
    }


    //todo  从配置中心,加载短信号码
    private List<String> getRelatedPerson() {
        return Collections.emptyList();
    }


}


在这里插入图片描述

5.prometheus+alertmanager 实现监控预警总结

回顾一下,时间相关参数

参数名称 说明 默认值 参数所属
scrape_interval 指标数据采集间隔 1分钟 prometheus.yml
evaluation_interval 规则的计算间隔 1分钟 prometheus.yml
for: 时间 异常持续多长时间发送告警 0 规则配置
group_wait 分组等待时间。同一分组内收到第一个告警等待多久开始发送,目的是为了同组消息同时发送 30秒 alertmanager.yml
group_interval 上下两组发送告警的间隔时间。第一次告警发出后等待group_interval时间,开始为该组触发新告警 5分钟 alertmanager.yml
repeat_interval 重发间隔。告警已经发送,且无新增告警,再次发送告警需要的间隔时间 4小时 alertmanager.yml

alertmanager配置功能确认很强大,完全能够按照自己的目标定义灵活的通知和报警方式,尤其是对webhook的支持,简直不能更灵活了。

而且alertmanager还支持定义template来更清晰的彰显要通知的内容。

但是本人还没有发现alertmanager该怎么进行配置的热加载,后面还要再研究下怎么优化通知,避免告警轰炸和提高告警的准确性。

参考文献:

https://prometheus.io/download/

说在最后:有问题找老架构取经

怎么做 指标的治理?

怎么做监控预警?

以上的内容,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。

最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。

在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。很多小伙伴刷完后, 吊打面试官, 大厂横着走。

在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。

遇到职业难题,找老架构取经, 可以省去太多的折腾,省去太多的弯路。

尼恩指导了大量的小伙伴上岸,前段时间,刚指导一个40岁+被裁小伙伴,拿到了一个年薪100W的offer。

狠狠卷,实现 “offer自由” 很容易的, 前段时间一个武汉的跟着尼恩卷了2年的小伙伴, 在极度严寒/痛苦被裁的环境下, offer拿到手软, 实现真正的 “offer自由” 。

技术自由的实现路径:

实现你的 架构自由:

吃透8图1模板,人人可以做架构

10Wqps评论中台,如何架构?B站是这么做的!!!

阿里二面:千万级、亿级数据,如何性能优化? 教科书级 答案来了

峰值21WQps、亿级DAU,小游戏《羊了个羊》是怎么架构的?

100亿级订单怎么调度,来一个大厂的极品方案

2个大厂 100亿级 超大流量 红包 架构方案

… 更多架构文章,正在添加中

实现你的 响应式 自由:

响应式圣经:10W字,实现Spring响应式编程自由

这是老版本 《Flux、Mono、Reactor 实战(史上最全)

实现你的 spring cloud 自由:

Spring cloud Alibaba 学习圣经》 PDF

分库分表 Sharding-JDBC 底层原理、核心实战(史上最全)

一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之间混乱关系(史上最全)

实现你的 linux 自由:

Linux命令大全:2W多字,一次实现Linux自由

实现你的 网络 自由:

TCP协议详解 (史上最全)

网络三张表:ARP表, MAC表, 路由表,实现你的网络自由!!

实现你的 分布式锁 自由:

Redis分布式锁(图解 - 秒懂 - 史上最全)

Zookeeper 分布式锁 - 图解 - 秒懂

实现你的 王者组件 自由:

队列之王: Disruptor 原理、架构、源码 一文穿透

缓存之王:Caffeine 源码、架构、原理(史上最全,10W字 超级长文)

缓存之王:Caffeine 的使用(史上最全)

Java Agent 探针、字节码增强 ByteBuddy(史上最全)

实现你的 面试题 自由:

4800页《尼恩Java面试宝典 》 40个专题

免费获取11个技术圣经PDF:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章