前提需求:告警规则和告警发送通知策略都动态配置在数据库,方便管理和随时修改、删除。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:
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服务。
(2)Alertmanager发送的告警消息通常是JSON格式的。你需要编写代码来解析这些JSON消息,提取告警标题、描述、标签等信息。
3.2 定时任务定时扫描告警消息表
(1)需要写一个定时任务方法,定时扫描告警消息表,查询待发送的告警消息,获取到待发送的告警消息集合
3.3 根据通知策略表的通知时间段、通知周期判断消息何时发送
(1)查询当前时间是否在通知时间段-开始、通知时间段-结束 时间区间之间;不在则跳过该条消息,在则继续下一步。
(2)根据告警策略唯一ID去 告警消息表查询最近一次发送告警的时间,然后根据当前时间 - 最近一次发送告警时间;如果小于通知周期时间则跳过该条消息;大于则进行下一步。