2. 运维监控体系搭建:Prometheus + Grafana 监控特征存储、计算节点与 API 网关
监控体系,说白了就是运维人员的眼睛。没有它,你就像在黑夜里开车——出了故障只能靠摸。我在搭建特征平台初期,就吃过这个亏。有一次计算节点内存泄漏,直到用户反馈特征获取超时,我们才发现节点已经 OOM 重启三次了。嗯,从那以后,我第一件事就是把监控体系立起来。
这一章,我们聚焦三个核心组件:特征存储、计算节点和 API 网关。我会用 Prometheus 做指标采集,Grafana 做可视化展示。下面直接上实战。
2.1 整体架构设计
先看一张图,理清数据流和组件关系。
核心思路很简单:每个组件暴露 /metrics 端点,Prometheus 定期拉取,Grafana 负责展示和告警。我个人习惯把告警规则也写在 Grafana 里,这样配置统一,不用再维护一套 Alertmanager 的规则文件。
2.2 特征存储监控
特征存储是特征平台的心脏。我见过太多因为存储抖动导致特征获取延迟的案例。监控重点放在连接数、延迟和内存上。
2.2.1 Redis 监控(以 Redis 为例)
Redis 的 Prometheus exporter 很成熟。我用的是 redis_exporter,直接暴露指标。
# 启动 redis_exporter
./redis_exporter \
--redis.addr=localhost:6379 \
--web.listen-address=0.0.0.0:9121
# 验证指标
curl http://localhost:9121/metrics | grep redis
关键指标我列在下面:
| 指标名 | 含义 | 告警阈值 |
|---|---|---|
redis_connected_clients |
当前连接数 | > 最大连接数 80% |
redis_memory_used_bytes |
已用内存 | > maxmemory 85% |
redis_db_keys |
Key 数量 | 突增 50% 以上 |
redis_commands_duration_seconds_total |
命令执行耗时 | P99 > 100ms |
--check-keys= 参数,只监控关键 DB。
2.2.2 自定义存储指标
如果特征存储是自己封装的 SDK(比如基于 MySQL 或 HBase),我建议在 SDK 内部埋点。用 Prometheus 的 client 库暴露自定义指标。
from prometheus_client import Histogram, Gauge, start_http_server
# 特征读取延迟
feature_read_latency = Histogram(
'feature_read_latency_seconds',
'Feature read latency in seconds',
buckets=[0.001, 0.005, 0.01, 0.05, 0.1, 0.5]
)
# 存储连接池状态
storage_conn_pool_size = Gauge(
'storage_conn_pool_size',
'Current connection pool size'
)
# 在读取特征时记录
def get_feature(key):
with feature_read_latency.time():
return storage.get(key)
嗯,这里要注意:指标名一定要规范。我见过团队里有人用 feature_read_time,有人用 read_feature_latency,最后 Grafana 面板上乱成一团。建议统一用 <组件>_<操作>_<单位> 的格式。
2.3 计算节点监控
计算节点负责特征加工,通常是流式作业(Flink)或批处理(Spark)。监控的核心是处理延迟和背压。
2.3.1 Flink 作业监控
Flink 自带 Prometheus 集成,在 flink-conf.yaml 里配置:
metrics.reporter.prom.class: org.apache.flink.metrics.prometheus.PrometheusReporter
metrics.reporter.prom.port: 9249
然后 Prometheus 配置抓取:
scrape_configs:
- job_name: 'flink'
static_configs:
- targets: ['flink-jobmanager:9249', 'flink-taskmanager-1:9249']
我重点关注的 Flink 指标:
flink_taskmanager_job_task_operator_currentNumberOfElementsInBuffer—— 背压信号,超过 100 就要警惕flink_jobmanager_job_latency_source_id_operator_id_operator_subtask_operator_latency—— 端到端延迟,P99 超过 5 秒就要排查flink_jobmanager_job_numberOfFailedCheckpoints—— 检查点失败次数,连续失败 3 次触发告警
2.3.2 自定义计算节点
如果计算节点是自己写的(比如 Python 进程),我建议用 prometheus_client 暴露处理进度和错误率。
from prometheus_client import Counter, Gauge
# 处理记录数
records_processed = Counter('records_processed_total', 'Total records processed')
# 当前处理延迟(秒)
processing_lag = Gauge('processing_lag_seconds', 'Current processing lag')
# 每处理一批数据更新
def process_batch(batch):
records_processed.inc(len(batch))
processing_lag.set(time.time() - batch[-1].timestamp)
2.4 API 网关监控
API 网关是特征平台的入口。用户能不能拿到特征,全看网关稳不稳。监控重点:QPS、延迟、错误率。
2.4.1 Nginx 监控(以 Nginx 为例)
Nginx 用 nginx-prometheus-exporter 暴露指标。前提是 Nginx 开启 stub_status。
# nginx.conf 配置
location /nginx_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
# 启动 exporter
./nginx-prometheus-exporter \
--nginx.scrape-uri=http://localhost:80/nginx_status
关键指标:
| 指标名 | 含义 | 告警阈值 |
|---|---|---|
nginx_connections_active |
活跃连接数 | > worker_connections 80% |
nginx_http_requests_total |
总请求数 | 用于计算 QPS |
nginx_up |
Nginx 是否存活 | 0 触发告警 |
2.4.2 自定义 API 网关指标
如果网关是自己写的(比如基于 Go 或 Java),我建议在中间件里统一采集。下面是一个 Go 的例子:
import "github.com/prometheus/client_golang/prometheus"
var (
httpRequestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "HTTP request latency in seconds",
Buckets: []float64{0.01, 0.05, 0.1, 0.5, 1, 5},
},
[]string{"path", "method", "status"},
)
httpRequestsTotal = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests",
},
[]string{"path", "method", "status"},
)
)
2.5 Grafana 仪表盘搭建
数据采集好了,接下来就是可视化。我一般按组件分 Dashboard,每个 Dashboard 包含 4-6 个核心面板。
2.5.1 特征存储仪表盘
- 连接数趋势:折线图,展示过去 1 小时连接数变化
- 内存使用率:仪表盘图,显示当前内存占比
- 命令延迟 P99:热力图,按命令类型分组
- Key 数量变化:面积图,观察是否有突增
2.5.2 计算节点仪表盘
- 处理延迟:时间序列图,展示端到端延迟
- 背压状态:热力图,按算子分组
- 检查点状态:状态图,显示成功/失败次数
- 吞吐量:折线图,展示每秒处理记录数
2.5.3 API 网关仪表盘
- QPS 趋势:折线图,按路径分组
- 延迟分布:柱状图,展示 P50/P90/P99
- 错误率:饼图,按状态码分组
- 上游健康:状态列表,显示每个上游节点的存活状态
2.6 告警规则配置
告警不是越多越好。我见过有人配了 50 条告警规则,结果天天被骚扰,最后大家直接忽略告警。我的原则是:每条告警都要能对应一个明确的故障场景。
下面是我常用的几条核心告警规则:
| 告警名称 | 表达式 | 严重级别 | 响应时间 |
|---|---|---|---|
| 存储连接池耗尽 | redis_connected_clients / redis_config_maxclients > 0.8 |
P0 | 5 分钟 |
| 计算节点背压 | flink_taskmanager_job_task_operator_currentNumberOfElementsInBuffer > 100 |
P1 | 15 分钟 |
| API 网关 5xx 率 | rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.01 |
P0 | 立即 |
| 特征读取延迟突增 | histogram_quantile(0.99, rate(feature_read_latency_seconds_bucket[5m])) > 0.1 |
P1 | 10 分钟 |
2.7 小结
监控体系搭建,说白了就是三个步骤:埋点、采集、展示。埋点要规范,采集要稳定,展示要直观。我个人习惯是先搭一个最小可用版本,再逐步完善。别想着一步到位,先把核心指标跑起来,后面再慢慢加细节。