前提需求:告警规则和告警发送通知策略都动态配置在数据库,方便管理和随时修改、删除。Prometheus需要动态读取数据库配置的告警规则,并根据数据的通知策略(邮件、短信、钉钉、微信等)把告警发送出去

需求分析:下面主要从表设计、组件配置、代码逻辑设计几个方面介绍。

1. 表设计

1.1 告警规则表

字段名 字段类型 说明
id int ID主键
notice_id int 通知策略ID
name varchar 告警名称
rule varchar 告警规则
duration varchar 持续时间
content varchar 告警内容
annotation varchar 注释
tag varchar 标签

1.2 通知策略表

字段名 字段类型 说明
id int 主键ID
name varchar 策略名称
start_time varchar 通知时间段-开始时间
end_time varchar 通知时间段-结束时间
cycle varchar 通知周期
type varchar 通知方式(短信、微信、钉钉、邮件等)
contact varchar 电话或者邮箱地址

1.3 告警消息表

字段名 字段类型 说明
id int 主键ID
告警标题 varchar 告警标题
告警内容 varchar 告警内容
告警规则唯一ID varchar 告警规则唯一ID
通知策略ID varchar 通知策略ID
创建时间 varchar 创建时间
更新时间 varchar 更新时间
发送状态 varchar 0未发送;1已发送

2. Prometheus、Alertmanager组件配置

2.1 告警规则YML文件

2.2 Alertmanager.YML文件配置

点击查看代码
route:
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 1s
  group_interval: 30s
  repeat_interval: 40s
  receiver: 'web.hook'
receivers:
  - name: 'web.hook'
    webhook_configs:
      - url: 'http://localhost:8092/api/v1.0/noticeStrategy/addMsg'

2.3 Prometheus.YML文件配置

点击查看代码
global:
  scrape_interval: 15s
  evaluation_interval: 15s
alerting:
  alertmanagers:
    - static_configs:
        - targets: ['localhost:9093']
rule_files:
  - "/Users/wjf/Desktop/yml/*.yml"

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]
  - job_name: "node"
    static_configs:
      - targets: ["localhost:9100"]

3. 代码逻辑设计

3.0 根据数据生成告警规则YML文件

SnakeYAML生成Prometheus告警规则.yml文件

点击查看代码
 // 创建告警规则对象  
        List<Map<String, Object>> rules = new ArrayList<>();  
          
        Map<String, Object> alertRule = new HashMap<>();  
        alertRule.put("alert", "HighRequestLatency");  
        alertRule.put("expr", "job:request_latency_seconds:mean5m{job=\"myjob\"} > 1");  
        alertRule.put("for", "10m");  
        Map<String, String> labels = new HashMap<>();  
        labels.put("severity", "page");  
        alertRule.put("labels", labels);  
        Map<String, String> annotations = new HashMap<>();  
        annotations.put("summary", "High request latency");  
        annotations.put("description", "The job {{ $labels.job }} has a high request latency.");  
        alertRule.put("annotations", annotations);  
        rules.add(alertRule);  
  
        // 创建告警规则组对象  
        Map<String, Object> ruleGroup = new HashMap<>();  
        ruleGroup.put("name", "example-group");  
        ruleGroup.put("rules", rules);  
  
        // 创建顶级对象结构  
        Map<String, Object> root = new HashMap<>();  
        root.put("groups", List.of(ruleGroup));  
  
        // 配置YAML的序列化选项  
        DumperOptions options = new DumperOptions();  
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);  
        options.setPrettyFlow(true);  
        Yaml yaml = new Yaml(options);  
  
        // 将告警规则对象序列化为YAML字符串  
        String yamlString = yaml.dump(root);  
  
        // 将YAML字符串写入文件  
        try (FileWriter writer = new FileWriter("alert_rules.yml")) {  
            writer.write(yamlString);  
        } catch (IOException e) {  
            e.printStackTrace();  
        } 

3.1 将Alertmanager的告警消息保存到MySQL数据库

(1)Alertmanager的配置文件中设置一个Webhook,以便在触发告警时发送HTTP POST请求到你的Java服务。
image
(2)Alertmanager发送的告警消息通常是JSON格式的。你需要编写代码来解析这些JSON消息,提取告警标题、描述、标签等信息。

3.2 定时任务定时扫描告警消息表

(1)需要写一个定时任务方法,定时扫描告警消息表,查询待发送的告警消息,获取到待发送的告警消息集合

3.3 根据通知策略表的通知时间段、通知周期判断消息何时发送

(1)查询当前时间是否在通知时间段-开始、通知时间段-结束 时间区间之间;不在则跳过该条消息,在则继续下一步。
(2)根据告警策略唯一ID去 告警消息表查询最近一次发送告警的时间,然后根据当前时间 - 最近一次发送告警时间;如果小于通知周期时间则跳过该条消息;大于则进行下一步。