指标计算(yidun-checker-metrics)
规则里那句「近 1 小时登录超过 10 次」,数字就是这个服务算出来的。
1. 业务定位
把统计口径定义为可配置的指标,在请求时实时返回一个 Double 值:
- 例:某账号近 1 小时登录次数、某设备当日去重账号数、某 IP 近 10 分钟请求量。
- 上游:策略中心三个可部署端通过 Dubbo 调用计算与管理接口。
- 下游:同步指标写 Redis 供后续请求读取;异步指标经 Kafka 计算后落 Redis;调度任务把结果快照到 Elasticsearch 供管理端查历史。
2. 架构与模块划分
| 模块 | 类型 | 职责 |
|---|---|---|
common | jar | StatisticType、StatisticFunctionType、WindowType 等枚举 |
domain | jar | 指标模型、聚合函数实体 |
service/base | jar | DAO、Redis/HBase/ES/Kafka 组件、本地缓存、条件编解码 |
service/business | jar | 计算引擎、指标读写、结果快照 |
facade/dubbo-provider | app | 同步计算入口(MetricsCalculateServiceImpl) |
execution/dubbo-api | jar | V2 计算契约 |
console/console-dubbo-provider | app | 指标管理后台 |
mq/calculate-async | app | 异步指标计算消费 |
scheduler | app | 结果快照到 ES |
3. 核心链路
同步与异步的分工是性能设计的关键:
- 同步指标:请求时当场算,走 Redis Lua,适合高频、简单计数。
- 异步指标:投递 Kafka 后台算,请求只读已有结果,适合重计算与跨表聚合。
4. 关键数据模型
| 对象 | 关键内容 |
|---|---|
MetricsInfoDo | 指标编码、统计类型、窗口、聚合函数、存储类型、过滤条件 |
StatisticsInfo | 指标实例配置 |
| 过滤条件 | V1/V2 双协议,操作符编码由 MetricFilterConditionCodec 转换 |
| 计算结果 | Map<指标code, Double>,供规则条件直接比较 |
窗口类型决定语义:滑动窗口按请求时间回看,固定窗口按自然时间对齐。两者在边界请求上的结果不同,是「数据对不上」的常见原因。
5. 存储与中间件
| 组件 | 用途 |
|---|---|
| Redis | 实时计数(Lua 原子操作)、最终指标值 |
| HBase | 异步计算中间结果(可选依赖,部分部署不含) |
| Elasticsearch | 指标结果历史快照,供管理端查询 |
| Kafka | 异步计算任务 mq/calculate-async |
| MySQL | 指标配置 |
| Caffeine | 配置本地缓存 MetricsInfoConfigCache |
6. 设计模式与扩展点
| 扩展点 | 位置 | 说明 |
|---|---|---|
| 聚合函数 | domain/function/Function* | 新增统计方式实现函数类 |
| 计算引擎 | RedisCalculateEngine、RedisSetCalculator | 切换存储/算法 |
| 过滤条件协议 | MetricFilterConditionValidator / Codec | V1/V2 兼容与校验 |
| 指标编码生成 | MetricsCodeGenerator | 编码规约 |
7. 上下游依赖
| 方向 | 模块 | 说明 |
|---|---|---|
| 上游 | mplatform-strategy | execution/center/management 三端调用 |
| 下游 | mplatform-meta | 输入字段路径解析(MetaFieldDefCache) |
| 下游 | mplatform-event | 指标配置缓存刷新事件 |
8. 工程约束与变更红线
- Redis 计算必须走 Lua,多步读写不能拆成多次命令,否则并发下计数错误。
- 配置缓存按
modify_time增量刷新,执行期不查配置库。 - HBase 是可选依赖,指标执行部署可能不含 HBase,新增逻辑必须允许其缺失。
- 指标编码不可复用:编码被规则条件引用,删除后重建会导致历史规则失效。
- 窗口语义改动需评估:滑动 ↔ 固定切换会让同一规则命中率突变。
9. 关键代码索引
| 主题 | 路径 | 说明 |
|---|---|---|
| 同步计算入口 | yidun-checker-metrics/facade/dubbo-provider/src/main/java/.../MetricsCalculateServiceImpl.java | 主入口 |
| 指标切片解析 | yidun-checker-metrics/service/business/src/main/java/.../MetricsSliceParser.java | 请求 → 计算任务 |
| 计算引擎 | yidun-checker-metrics/service/business/src/main/java/.../calculator/RedisCalculateEngine.java | Redis 聚合 |
| 异步消费 | yidun-checker-metrics/mq/calculate-async/src/main/java/.../CalculateConsumer.java | Kafka 计算 |
| 条件编解码 | yidun-checker-metrics/service/base/src/main/java/.../localcache/MetricFilterConditionCodec.java | V1/V2 协议 |
| 结果快照 | yidun-checker-metrics/scheduler/src/main/java/.../MetricsResultSnapshotTask.java | Redis → ES |
10. 排查要点
| 现象 | 定位 | 结论 |
|---|---|---|
| 指标值恒为 0 | 看输入字段是否取到值、Redis key 是否写入 | 字段 code 错或过滤条件过严 |
| 指标值与实际不符 | 比对窗口类型与时间边界 | 滑动/固定窗口语义差异 |
| 指标返回慢 | 看同步/异步配置 | 重计算指标被配成同步 |
| 历史查不到 | 看快照任务是否执行 | MetricsResultSnapshotTask 失败或延迟 |
| 配置改了不生效 | 看本地缓存刷新时间 | modify_time 增量刷新未触发 |