3. 监控系统选型:Prometheus + Grafana方案、ELK日志监控方案、自定义埋点方案、选型对比与决策
监控系统选型,说白了就是给特征平台装一套「体检设备」。你想想看,一个每天处理几亿特征数据的平台,要是出了问题你都不知道,那跟开盲盒有什么区别?
我个人习惯把监控方案分成三大流派:指标监控、日志监控和自定义埋点。每个流派都有自己的看家本领,也有各自的短板。今天我们就来掰扯清楚,到底该怎么选。
3.1 Prometheus + Grafana:指标监控的扛把子
这套组合在云原生圈子里有多火,不用我多说。Prometheus 负责采集和存储时序数据,Grafana 负责可视化展示。我最早接触 Prometheus 是在 2018 年,当时还在做微服务改造,一用就回不去了。
核心架构
特征服务 → Prometheus Client (暴露 /metrics 端点)
↓
Prometheus Server (拉取 + 存储)
↓
Grafana (查询 + 告警 + 仪表盘)
Prometheus 采用的是 Pull 模型,也就是服务端主动去拉取目标的数据。这一点跟传统的 Push 模型(比如 Zabbix)很不一样。Pull 模型的好处是:你不需要在每个服务里配上报地址,只要统一在 Prometheus 配置文件里声明目标就行。
特征平台关键指标示例
feature_ingestion_latency_seconds—— 特征写入延迟feature_retrieval_total—— 特征查询总量(带 status 标签)feature_storage_usage_bytes—— 存储使用量feature_sla_violation_total—— SLA 违约次数
Grafana 这边,我建议你提前把仪表盘模板化。我在项目中遇到过一个问题:每次新接入一个特征源,就要手动拖一遍面板,太累了。后来我们统一用 Grafana Provisioning 的方式,把仪表盘定义成 JSON 文件,放到 Git 里管理。新服务上线,自动生成对应的监控面板。
小技巧:Prometheus 的告警规则建议用 for 字段做「持续时间」判断。比如特征延迟超过 5 秒持续 1 分钟才告警,避免因为瞬时抖动而收到一堆垃圾告警。
3.2 ELK日志监控方案:日志里的金矿
ELK(Elasticsearch + Logstash + Kibana)是日志监控的经典组合。很多人觉得日志就是用来排错的,其实不然。日志里藏着大量有价值的信息——用户行为、异常堆栈、性能瓶颈,全都有。
ELK 在特征平台中的典型用法
特征服务 → Filebeat (采集日志) → Logstash (解析/过滤) → Elasticsearch (存储/索引) → Kibana (搜索/可视化)
我记得有一次线上特征数据出现异常,Prometheus 指标显示一切正常,但业务方反馈特征值不对。最后查了半天,是某个特征计算逻辑里有个边界条件没处理好。要不是 ELK 里保留了完整的请求日志,这个问题根本定位不了。
ELK 的优势在于全量数据留存和灵活搜索。Prometheus 只能存聚合后的指标,但 ELK 可以存每一条原始日志。这对于事后审计和根因分析来说,价值巨大。
注意:ELK 的存储成本很高。特征平台每天产生的日志量可能达到 TB 级别。我建议做分层存储:热数据保留 7 天,温数据保留 30 天,冷数据归档到对象存储。别一股脑全塞进 Elasticsearch,否则账单会让你怀疑人生。
日志结构化是关键
很多团队用 ELK 效果不好,是因为日志格式太随意。我建议统一使用 JSON 格式输出日志,并且定义好字段规范:
{
"timestamp": "2024-01-15T10:30:00.123Z",
"level": "ERROR",
"service": "feature-ingestion",
"feature_name": "user_click_rate_v2",
"latency_ms": 5230,
"error_code": "TIMEOUT",
"trace_id": "abc123def456",
"message": "特征计算超时,已触发降级"
}
这样 Logstash 解析起来效率高,Kibana 里做聚合分析也方便。你想想看,如果日志是纯文本的,想统计某个特征的平均延迟,得写多复杂的正则?
3.3 自定义埋点方案:灵活但代价高
有些场景,Prometheus 和 ELK 都搞不定。比如:
- 你想统计某个特征在特定业务场景下的调用链路耗时
- 你想记录用户在一次请求中,特征命中缓存的次数
- 你想追踪特征数据从产生到消费的端到端延迟
这时候就需要自定义埋点了。说白了,就是在代码里主动打点,把数据上报到专门的存储系统。
常见的自定义埋点实现方式
// 伪代码示例:特征命中率埋点
public class FeatureHitCounter {
private final Counter hitCounter = Metrics.counter("feature_cache_hit");
private final Counter missCounter = Metrics.counter("feature_cache_miss");
public FeatureValue getFeature(String name) {
FeatureValue value = cache.get(name);
if (value != null) {
hitCounter.inc();
} else {
missCounter.inc();
value = computeFeature(name);
cache.put(name, value);
}
return value;
}
}
自定义埋点的好处是精准,你想埋什么就埋什么。但代价也很明显:
- 侵入性强:需要修改业务代码
- 维护成本高:埋点多了,代码里到处都是打点逻辑
- 存储压力大:自定义指标往往维度很多,容易导致基数爆炸
我的建议:自定义埋点只用于「Prometheus 和 ELK 覆盖不到」的核心场景。比如特征端到端延迟、缓存命中率、降级触发次数。其他常规指标,能用 Prometheus 解决的,就别自己造轮子。
3.4 选型对比与决策
好了,三种方案都介绍完了。到底怎么选?我画了一张对比图,帮你理清思路。
下面这张表,是我在实际项目中总结的选型对比,你可以直接拿来参考:
| 对比维度 | Prometheus + Grafana | ELK 日志方案 | 自定义埋点 |
|---|---|---|---|
| 数据形态 | 时序指标(聚合后) | 原始日志(全量) | 自定义指标/事件 |
| 存储成本 | 低(聚合存储) | 高(全量存储) | 中(取决于维度) |
| 查询延迟 | 毫秒级 | 秒级 | 取决于后端 |
| 告警能力 | 强(内置 Alertmanager) | 中(需额外配置) | 需自建 |
| 代码侵入 | 低(SDK 接入) | 低(日志框架) | 高(业务代码) |
| 适用场景 | 性能监控、SLA 告警 | 故障排查、审计 | 业务指标、链路追踪 |
我的最终建议:
- 中小规模团队(特征量 < 1000):Prometheus + Grafana 就够了,日志用 ELK 做辅助
- 大规模团队(特征量 > 10000):三种方案都要上,但要有清晰的职责划分。我曾经见过一个团队,三种方案各搞各的,最后告警重复、数据对不上,反而增加了运维负担
- 关键原则:能用 Prometheus 解决的,不要用 ELK;能用 ELK 解决的,不要自定义埋点。每多一种方案,就多一份维护成本
嗯,监控系统选型这块,说到底没有银弹。关键是要想清楚:你真正需要监控的是什么?是性能、是可用性、还是业务正确性?想清楚了,选型自然就清晰了。