一,概要
- alarm的功能设计参考oneapm功能规划,下面将详细描述。
- 也参考开源skywalking,pinpoint等监控告警系统,确定流式计算是解决报警最好方案。
二,功能概要
1.报警策略
- 报警策略用来描述关联的监控对象与指标类型。
- 策略包括(总览属性,报警对象,通知对象,匹配条件)
字段 | 规则 | 业务描述 |
---|---|---|
策略名称 | 唯一性, | 代表一个报警策略 |
应用名称或集群名称 | 多选 | 参考onepam应该支持多选app。具体的监控对象 |
应用实例或集群节点 | 按类型多选 | 具体的监控对象实例 |
监控指标 | 字典表 | web请求,JvM,jdbc等 |
监控维度项 | 字典表 | 关联监控指标所拥有的维度 |
何时可用规则 | 参考oneapm,具体意思指定时间段内规则是否生效。 增对时间段监控 | |
等待时间 | 报警规则每分钟都在进行计算,当报警事件开启后且报警对象持续n分钟,一直处于严重或警告条件时,会触发报警持续事件。 避免连续收到大量通知。 |
- 疑问应用名称或集群名称是否需要多选,oneapm支持,对应op来说也需要支持多选。
- 等待时间:举个例子,对于一项叫“check out”的业务来说,假设你的等待时间设定的是30分钟,并且在13:00的时候产生了一个“严重”的报警,那么在30分钟之后的13:30才会进行新一轮的持续报警event,除非状态变为了“警告”或者报警已经被处理。假如在13:05“check out”业务的报警状态变成了“警告”,那么就会开始新一轮的报警等待,也就是说会在13:35进行“警告”的报警通知。
2.触发条件
- 参考oneapm,多组匹配条件应该在一个时间窗口里,否则时间窗口无法控制。
- 对于触发条件可以定义两个等级,严重,警告。
字段 | 规则 | 业务描述 |
---|---|---|
报警类型 | 严重,警告 | 代表event type |
时间窗口 | 3,5,10,15,30,60 分钟可选 | 用于计算时间范围值 |
多条件关系 | all,any | |
监控算法 | 平均值,至少一次,总是 | |
运算符 | 大于,小于 | |
报警阀值 | 关联监控指标所拥有的维度 |
3. 疑问?是否需要把监控维度项放在触发条件中选择,形成多个监控维度项匹配。
- 数据丢失告警
- 警告条件中输入的分钟数至少要2分钟;严重条件中输入的分钟数要大于警告条件中输入的分钟数。
- 我们只需要简单设计在n分钟内没获取data就告警。
3.告警事件
- 通过page可以查询该策略产生的event通知记录,存储在mongodb中。
- 通道email通知事件。
三,数据库
- 表alarm_strategy对应报警策略信息
- 表alarm_strategy_instance 对应的报警策略实例选择
- 表alarm_strategry_condition 触发条件
四,alarm架构结构图
1.介绍
- 采用kafka stream来消费all metrics信息。移除以前的topic分配策略,采用kafka rebalance来自动管理instance。
- 本地Cache所有strategry信息,2分钟同步一次数据。
- kafka stream的FilterProcessor根据cache strategry过滤接收到message。
ReduceProcessor的根据message及strategry计算匹配condition。如果满足则发送alarmEvent消息事件。
alarmEvent消费处理器,根据strategry等待时间是否持久化并通知用户的告警。
2.疑问
- 需要明确对一个AppName一类metric消息是分散多个sentry实例,还是一个实例。这个对于ReduceProcessor聚合运算来说是前提。
- 目前的sentry使用大量localCache来存储聚合窗口结果。如果AppName一类metric消息分散多个实例,则不能达到一致。
- 目前每个metric消息是按照hashCode指定为kafka消息key的。能保证同一个AppName同一类metric消息是在一个sentry实例上。
4.
"category": "http-metrics",
String sourceAppName = entity.getAppName();
String sourceHostName = entity.getHostName() + ":" + entity.getPort();
// 搜索调用者id是否已存储
Long sourceMetadataId = appMetadataManager.searchAppRecord(AppMetadataParseConstant.ROOT, MetadataTypeConstant.JAVA_APP, sourceAppName);
Long hostId = appMetadataManager.searchAppRecord(sourceMetadataId, MetadataTypeConstant.INSTANCE, sourceHostName);
metricMap.put("appName", sourceMetadataId);
metricMap.put("hostName", hostId);
metricMap.put(Constants.HASH_CODE, HashCodeUtil.getHashCode(sourceAppName));