ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

VictoriaMetrics 构建 AI 模型服务可观测性监控体系

VictoriaMetrics 构建 AI 模型服务可观测性监控体系 你负责的推荐模型今天凌晨悄悄“变笨”了。用户点击率掉了 5%但 CPU、内存、网络带宽全部正常服务也没有任何报错。你翻遍了 Grafana 面板除了感叹“指标真全”找不到任何异常。直到有人提醒你模型上线之后的性能变化你监控过它的置信度吗这是 AI 应用落地里一个特别真实的场景。传统 Web 服务的监控体系只能回答“服务器挂了没有”却回答不了“模型效果衰减了没有”。而要回答后者需要一套能承载模型指标、支持多维查询、扛得住高基数写入的数据底座。VictoriaMetrics 正是这一类产品里非常值得关注的选择。这篇文章不会只讲 VictoriaMetrics 怎么安装。我会结合 AI 模型服务的实际场景讲清楚为什么传统监控不够、AI 场景需要采集哪些指标、VictoriaMetrics 在整个链路里扮演什么角色并给出从部署到埋点、查询、告警的完整示例。读完你可以直接照着搭建一套面向 AI 服务的可观测性体系。先给一个判断VictoriaMetrics 真正的价值不在于它“兼容 Prometheus”而在于它把 AI 场景需要的指标存储、查询、压缩、降采样能力做成了开箱即用的工程方案。这句话下面会展开讲。1. 这篇文章真正要解决的问题先说痛点。做 AI 应用的人和做传统后端的人在“监控”这件事上的体感完全不一样。传统后端上线一个接口你关心的是 QPS、错误率、P99 延迟、CPU 和内存。这些指标从 Nginx、Spring Boot Actuator、Node.js 的 prom-client 里都能拿到随便套一个 Prometheus Grafana 就能看得很清楚。但 AI 服务不一样。模型推理服务的状态不止体现在“服务有没有报错”上还体现在这些地方推理延迟是否随着并发量升高而劣化模型返回的置信度分布是否发生漂移输入数据的特征分布是否和训练集不一致同一个模型的不同版本线上表现差异有多大GPU 显存、批处理大小、推理引擎线程数是否匹配。这些指标有个共同点它们都是典型的时间序列数据并且维度标签可能非常高。比如按模型名、版本号、输入来源、业务线来区分一个请求就可能产生几条甚至十几条序列。传统关系型数据库不适合做这件事。你不可能把每个请求的延迟都写进 MySQL 然后按时间做聚合那样写入压力和查询效率都撑不住。时序数据库就是为这类数据设计的。VictoriaMetrics 在这个领域里的优势很明显它兼容 Prometheus 协议迁移成本低单节点版性能出色资源占用比同类产品小支持 MetricsQL比 PromQL 更灵活自带降采样和数据保留机制可以控制存储成本。我见过不少团队模型服务已经上线了监控却还停留在“看进程还活着吗”这个级别。等到模型效果衰减、用户投诉增多才想起来要查历史数据却发现根本没埋点。这篇文章就是帮你把这一步补上。2. VictoriaMetrics 与 AI Policy先把概念拆清楚2.1 时序数据库到底解决什么问题时序数据库Time Series DatabaseTSDB解决的是一类特定问题高并发写入、按时间维度聚合查询、长时间范围扫描。你可以把它理解成一个专门为“每隔几秒记录一条带时间戳的数据”而优化的存储系统。普通数据库把每条数据当独立记录时序数据库则把同一标签集的数据按时间排列在一起存储和压缩效率更高。举个例子。你要监控一个模型服务的 P95 延迟传统做法是每分钟把聚合结果写一条记录到 MySQL。但如果你想看最近 7 天每 5 分钟的 P95MySQL 可以查但性能会随着数据量增长明显下降。时序数据库直接用一行查询解决并且底层通过压缩和分段存储让扫描范围远小于全表扫描。2.2 VictoriaMetrics 的核心特性VictoriaMetrics 是一个开源的时序数据库源码在 GitHub 上Apache 2.0 许可证。它有几个关键特性值得关注特性说明Prometheus 兼容支持 Prometheus 抓取协议和 remote writePrometheus 配置可以平滑迁移高性能写入批量写入、高效压缩单节点可支撑每秒百万级数据点写入资源占用低相比同类时序数据库内存占用更低适合部署在普通服务器上MetricsQL 查询在 PromQL 基础上扩展支持更丰富的聚合函数和语法糖降采样对旧数据自动降精度减少存储占用数据保留策略支持按天/按月配置保留周期自动清理过期数据集群模式需要水平扩展时可以部署 vmstorage、vminsert、vmselect 集群对 AI 场景来说最有用的是“高基数写入”能力和降采样能力。模型指标的标签丰富度非常高如果 Prometheus 的本地存储扛不住VictoriaMetrics 往往是不错的替代品。2.3 这里的 AI Policy 指什么标题里“AI Policy”这个短语第一眼容易让人以为是一份制度文件。但在技术语境里我更愿意把它理解为一套策略在 AI 应用落地过程中面向指标采集、数据存储、查询分析、告警治理制定的一整套规范和实践路径。Policy 不是指“AI 不能做什么”而是指“AI 应用的指标该怎么管”。比如模型版本号要不要作为标签置信度指标用 Histogram 还是 Summary数据保留 7 天还是 30 天告警阈值是固定值还是动态基线这些问题如果不在建设初期想清楚后期改起来非常痛苦。所以这篇文章的“AI Policy”实际上包含了三层数据采集层哪些模型指标需要采集埋点怎么做数据存储层用什么数据库存、存多久、如何控制存储成本数据消费层怎么查询、怎么可视化、怎么告警。3. AI 应用可观测性为什么传统监控不够3.1 传统监控与 AI 监控的差异很多人有一个误区认为 AI 服务的监控就是“在原有监控系统上加几个自定义指标”。从技术实现上看确实是这样但从方法论上看两者差异很大。对比维度传统 Web 服务监控AI 模型服务监控核心关注点服务可用性、性能、容量模型效果、推理性能、资源效率关键指标CPU、内存、QPS、错误率、RT推理延迟、置信度、特征分布、GPU 显存数据特征指标相对稳定阈值固定指标随数据分布变化需要动态判断告警逻辑超过固定阈值即触发需要结合基线、趋势、版本对比失败模式服务崩溃、超时服务正常但效果变差、静默失败最危险的 AI 事故不是服务崩溃而是“服务看起来一切正常但模型给出的结果已经不可用”。这种静默失败只有通过模型层指标才能发现。3.2 AI 场景需要采集哪些指标不同阶段的 AI 服务需要关注不同指标。以在线推理服务为例我建议至少采集以下四类第一类服务性能指标。包括 QPS、延迟分布、错误数。这部分和传统监控重叠但需要按模型名和版本号做细分。第二类模型质量指标。包括置信度分布、预测类别分布。置信度突然下降往往意味着输入数据分布发生变化或者模型被攻击。第三类资源消耗指标。包括 GPU 利用率、显存占用、CPU 内存、请求批处理大小。这些直接影响推理服务的成本和容量规划。第四类业务效果指标。比如推荐场景的点击率、搜索场景的转化率。这类指标不一定能从推理服务本身采集但可以通过业务日志接入时序数据库。3.3 整体数据链路架构把这四类指标汇总起来的架构大致如下模型推理服务 (暴露 /metrics) | v vmagent 或 Prometheus (抓取指标) | v VictoriaMetrics (存储与查询) | -- Grafana (可视化) | -- vmalert / Alertmanager (告警)这个链路里每个组件都可以替换。比如采集端可以用 Prometheus也可以用 VictoriaMetrics 自带的 vmagent告警可以用 vmalert也可以用 Alertmanager。核心是存储层统一到 VictoriaMetrics保证指标能长期保存、高效查询。4. 环境准备用 Docker Compose 搭建监控栈4.1 组件选择我推荐用 Docker Compose 在本地或测试环境完整跑一遍监控栈包含以下组件VictoriaMetrics 单节点版负责存储和查询提供:8428端口vmagent负责从模型服务抓取指标并写入 VictoriaMetricsGrafana负责可视化。使用 vmagent 而不是直接用 Prometheus是因为 vmagent 更轻量资源和配置也更简单。如果你对 Prometheus 更熟换成 Prometheus 也完全没问题VictoriaMetrics 支持 remote write 协议。4.2 编写 docker-compose.yml在空目录下创建docker-compose.yml# docker-compose.yml version: 3.8 services: victoriametrics: image: victoriametrics/victoria-metrics:latest container_name: vm-single restart: always ports: - 8428:8428 command: - --storageDataPath/vmsingle - --retentionPeriod7 - --httpListenAddr:8428 volumes: - vm_single_data:/vmsingle vmagent: image: victoriametrics/vmagent:latest container_name: vm-agent restart: always ports: - 8429:8429 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro command: - --promscrape.config/etc/prometheus/prometheus.yml - --remoteWrite.urlhttp://victoriametrics:8428/api/v1/write grafana: image: grafana/grafana:latest container_name: vm-grafana restart: always ports: - 3000:3000 environment: - GF_SECURITY_ADMIN_USERadmin - GF_SECURITY_ADMIN_PASSWORDadmin123 - GF_USERS_ALLOW_SIGN_UPfalse volumes: vm_single_data:关键参数说明retentionPeriod7表示数据保留 7 天单位是天也可以写成1或30实际按项目需求调整storageDataPath指定数据目录这里挂到 Docker 卷重启不丢数据vmagent 的remoteWrite.url指向 VictoriaMetrics 的写入接口/api/v1/writeGrafana 账号密码在环境变量里配置生产环境必须换成强密码不要用示例密码。4.3 创建抓取配置创建prometheus.yml这个是 vmagent 的抓取配置# prometheus.yml global: scrape_interval: 5s evaluation_interval: 5s scrape_configs: - job_name: ml-model-service static_configs: - targets: [model-api:8000]注意targets里的主机名是model-api。这是因为在 Docker Compose 网络里容器之间通过服务名访问。后续我们部署模型服务时容器名要和这里保持一致。4.4 启动验证执行启动命令docker compose up -d等待镜像拉取完成后检查状态docker compose ps然后验证 VictoriaMetrics 是否正常curl http://localhost:8428/health如果返回正常接着访问http://localhost:8428/vmui可以看到 VictoriaMetrics 自带的 Web 查询界面。5. 完整示例为模型推理服务接入指标采集这个部分我们用 Python 写一个模拟的模型推理服务。它不调用真实模型但会暴露标准 Prometheus 指标格式的/metrics接口足够演示完整链路。5.1 编写带指标埋点的推理服务创建model_api.py# model_api.py import random import time from flask import Flask, jsonify, request, Response from prometheus_client import ( Counter, Histogram, Summary, generate_latest, CONTENT_TYPE_LATEST, ) app Flask(__name__) # 请求总数按模型名和版本号分维度 REQUEST_COUNT Counter( model_requests_total, Total number of inference requests, [model_name, model_version], ) # 推理错误数按错误类型分维度 ERROR_COUNT Counter( model_errors_total, Total number of inference errors, [model_name, error_type], ) # 推理延迟直方图用于计算 P50/P95/P99 REQUEST_LATENCY Histogram( model_request_duration_seconds, Model inference request latency in seconds, [model_name], buckets(0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0), ) # 模型置信度摘要用于观测模型输出质量 CONFIDENCE_SUMMARY Summary( model_confidence, Prediction confidence of the model, [model_name], ) def inference(text: str): 模拟一次模型推理。 正常情况下置信度在 0.82~0.99 之间 有 5% 的概率返回较低置信度 用来模拟数据漂移导致的效果波动。 time.sleep(random.uniform(0.02, 0.3)) confidence random.uniform(0.82, 0.99) if random.random() 0.05: confidence random.uniform(0.45, 0.60) label positive if confidence 0.7 else negative return {label: label, confidence: round(confidence, 4)} app.route(/predict, methods[POST]) def predict(): data request.get_json() if not data or text not in data: return jsonify({error: text is required}), 400 model_name sentiment-v1 model_version v1.0 REQUEST_COUNT.labels(model_namemodel_name, model_versionmodel_version).inc() start time.time() try: result inference(data[text]) confidence result[confidence] CONFIDENCE_SUMMARY.labels(model_namemodel_name).observe(confidence) return jsonify(result) except Exception as exc: ERROR_COUNT.labels( model_namemodel_name, error_typetype(exc).__name__ ).inc() return jsonify({error: str(exc)}), 500 finally: latency time.time() - start REQUEST_LATENCY.labels(model_namemodel_name).observe(latency) app.route(/metrics) def metrics(): return Response(generate_latest(), mimetypeCONTENT_TYPE_LATEST) if __name__ __main__: app.run(host0.0.0.0, port8000)这段代码包含四个核心指标model_requests_total请求总数。带上model_name和model_version标签可以按版本对比流量model_errors_total错误数。带上error_type标签方便定位错误类型model_request_duration_seconds延迟直方图。用buckets指定分桶后续可以算 P95、P99model_confidence置信度摘要。这是 AI 场景特有的核心指标用于观察模型输出质量变化。注意异常处理的写法请求到达时先增加计数然后进入 try-finally 块保证无论成功还是失败延迟指标都会被记录。错误计数单独用 except 分支处理避免重复计数。5.2 编写 Dockerfile 和启动配置创建DockerfileFROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY model_api.py . EXPOSE 8000 CMD [python, model_api.py]创建requirements.txtflask prometheus-client然后构建并启动模型服务容器并让它加入和监控栈同一个 Docker 网络docker build -t model-api:latest .由于模型服务要出现在 vmagent 的抓取目标里需要把它加入同一个网络。这里我们通过 Compose 统一管理更方便。可以把模型服务补充到docker-compose.yml中也可以单独起容器时指定网络。推荐直接加进 Compose 文件再执行docker compose up -d如果模型服务在另一个 Compose 项目里可以用docker network connect把容器加到当前网络。实际项目里更推荐所有组件放在同一个 Compose 项目里维护。5.3 用 MetricsQL 查询核心指标部署完成后打开http://localhost:8428/vmui在输入框里执行以下查询。查询整体 QPSsum(rate(model_requests_total[5m]))查询 P95 推理延迟histogram_quantile( 0.95, sum(rate(model_request_duration_seconds_bucket[5m])) by (le) )查询最近 10 分钟的平均置信度sum(rate(model_confidence_sum[10m])) / sum(rate(model_confidence_count[10m]))这三个查询覆盖了 AI 监控最核心的三个维度流量、性能、质量。MetricsQL 的写法和 PromQL 基本一致如果你之前用过 Prometheus几乎不需要额外学习成本。5.4 配置告警规则创建alert-rules.yml通过 vmalert 或 Alertmanager 加载# alert-rules.yml groups: - name: ml-model-alerts rules: - alert: HighInferenceErrorRate expr: | sum(rate(model_errors_total[5m])) / sum(rate(model_requests_total[5m])) 0.05 for: 10m labels: severity: critical team: ml-platform annotations: summary: 模型服务错误率超过 5% - alert: LowModelConfidence expr: | (sum(rate(model_confidence_sum[10m])) / sum(rate(model_confidence_count[10m]))) 0.7 for: 15m labels: severity: warning team: ml-platform annotations: summary: 模型平均置信度低于 0.7这两条告警规则一个关注服务稳定性一个关注模型质量。注意LowModelConfidence的阈值不是拍脑袋定的应该来自模型评估阶段对置信度分布的统计分析。6. 运行结果与效果验证6.1 验证指标写入先用 curl 向模型服务发送几个请求curl -X POST http://localhost:8000/predict \ -H Content-Type: application/json \ -d {text: this movie is great}重复执行几次然后通过 VictoriaMetrics 查询验证数据是否写入。在 vmui 中执行model_requests_total如果看到返回了带model_namesentiment-v1的数据说明链路已经通了。也可以直接用 API 验证curl -G http://localhost:8428/api/v1/query \ --data-urlencode querysum(rate(model_requests_total[5m]))正常返回结果会包含一个result数组里面有具体的数值。6.2 配置 Grafana 数据源打开http://localhost:3000用 Compose 里配置的账号密码登录。然后添加数据源选择 PrometheusURL 填http://victoriametrics:8428。因为 Grafana 支持 Prometheus 数据源协议而 VictoriaMetrics 完全兼容该协议所以这里可以直接用 Prometheus 类型的数据源来连接 VictoriaMetrics。保存并测试连通性后新建一个 Dashboard添加 Panel查询语句和上一节写的 MetricsQL 一致即可。6.3 验证告警可以用一个简单的办法验证告警是否生效把模型服务的错误率人为调高比如删除inference函数、强制抛异常然后观察告警指标是否超过阈值。等for: 10m时间窗口过去后检查 vmalert 或 Alertmanager 是否收到告警。测试完记得把代码恢复。这里要特别提醒告警阈值在测试环境验证完成后不要一次性全量上生产。先从 warning 级别开始观察一段时间再调成 critical。7. 常见问题与排查思路问题现象可能原因排查方式解决方案vmagent 日志报connection refused目标服务没有启动或网络不通检查docker compose ps确认容器状态确保模型服务容器与 vmagent 在同一网络指标一直为 0抓取路径错误或抓取间隔未到访问http://localhost:8000/metrics手动验证确认/metrics接口返回 200 且内容包含指标名查询返回no data指标名写错或标签不匹配用{__name__~.*model.*}扩大匹配核对代码中注册的指标名磁盘占用增长过快数据保留周期过长或写入量很大查看victoriametrics数据目录大小调低retentionPeriod或开启降采样延迟直方图没有 P95查询语法有问题在 vmui 中执行model_request_duration_seconds_bucket确认数据存在检查 Histogram 的 buckets 是否合理Grafana 连接 VictoriaMetrics 一直失败数据源 URL 配置错误在 Grafana 容器内测试curl http://victoriametrics:8428/health使用容器服务名而不是 localhost除了表格里的内容还有两个常见场景需要补充。第一个是“模型服务重启后指标计数丢失”。Counter 这类指标如果存在进程内存里服务重启会从零开始。这在大多数场景下可以接受因为你通常关心的是rate()变化趋势而不是绝对值。但如果有人告诉你“服务重启后错误率暴涨”先确认一下是不是计数器归零导致的假象。第二个是“查询时发现时间范围没有数据”。VictoriaMetrics 默认只展示最近查询时间窗口的数据如果设置了过短的retentionPeriod超出保留期的数据会被自动删除。确认一下查询时间范围是否已经覆盖了数据保留周期。8. 最佳实践与工程建议8.1 指标命名与标签规范指标命名是 AI 监控最容易忽略的坑。命名不统一后面所有查询都要不断猜。建议采用项目_组件_指标单位的格式model_requests_total model_request_duration_seconds model_confidence_sum model_errors_total标签尽量控制在 5 个以内。每多一个标签基数就上升一个数量级。对 AI 场景来说model_name和model_version是必须的其余标签按需添加。不要把用户 ID、订单 ID 这种高基数字段放进去否则存储压力会急剧上升。8.2 数据保留与降采样策略VictoriaMetrics 的retentionPeriod参数决定数据保留时长。AI 场景下建议至少保留 30 天的原始指标方便做版本回归分析。如果磁盘压力大可以开启降采样把 7 天前数据按 1 小时粒度聚合降低存储成本。降采样是一个相对高级的功能线上开启前一定要在测试环境验证查询结果是否符合预期。降采样并不是简单的数据删减它会影响查询的精度所以像 P99 延迟这种指标降采样后可能偏乐观需要提前评估。8.3 高基数问题AI 场景的高基数和传统场景不太一样。传统场景的高基数来自 URL、用户 IDAI 场景的高基数来自模型版本、超参数组合、输入特征标识。一个有效的思路是把高基数的维度放在日志系统里不要把所有人都塞进指标系统。指标系统只保留低频、有限维度精确的请求级数据放到日志或链路追踪里。比如“某个版本的模型今天处理了多少请求”用指标系统“某个用户在某次请求里拿到什么结果”用日志系统。8.4 安全与权限边界VictoriaMetrics 默认没有任何认证机制生产环境必须放在内网或者通过反向代理做基本身份认证。不要直接把8428端口暴露到公网。Grafana 默认的管理员账号密码一定要修改。如果团队有多人使用建议开启 Grafana 的组织和团队权限让不同角色只能看到自己的面板和告警。涉及模型尚上线等关键操作必须遵守最小权限原则使用账号不能拥有修改配置的权限。8.5 告警策略先治聋再治哑AI 场景告警有一个特有难点指标波动强的正常波动往往被误报为故障。固定阈值很容易误伤。建议按顺序做这几件事先把所有关键指标接入保证“能看见”收集至少 2 到 4 周的正常数据观察波动范围基于真实数据设置告警阈值而不是拍脑袋告警级别先设 warning观察一段时间再升级为 critical定期复盘告警记录调低误报率。一个实用的原则宁可少告警不可乱告警。告警疲劳会导致工程师忽略真正重要的消息最终回到“告警全关只看人报”的老路。9. 结语从监控到治理回到文章开头那个场景。如果你的模型服务也有一天“悄悄变笨”最怕的不是没有告警而是没有数据可以查。VictoriaMetrics 的价值就是让你在需要回溯问题时所有指标都还在、都能查、都能关联。它解决的不只是“现在怎么了”更是“为什么变成这样”。这篇文章覆盖了从概念、架构到部署、埋点、查询、告警的完整路径。你可以先把 Docker Compose 那一节跑通再把model_api.py换成自己真实的模型服务接着按顺序接入指标和告警。建议先在测试环境完整跑一遍流程确认无误后再上生产并做好备份和数据保留规划。后续可以继续深入的方向包括VictoriaMetrics 集群模式的容量规划、MetricsQL 更复杂的聚合查询、模型漂移检测与告警联动、以及将推理服务的 trace 与指标打通形成全链路可观测性。每一步都能让 AI 应用的稳定性向前走一大截。如果想进一步探索可以直接阅读 VictoriaMetrics 官方文档中关于单节点运行参数和 MetricsQL 查询函数的章节。通过项目自带文档学习比任何二手资料都准确。
返回列表