当前位置: 首页 > news >正文

Prometheus错误率监控与告警实战:如何自定义规则精准预警服务器异常

更多云服务器知识,尽在hostol.com

你有没有过这种感觉:服务跑得挺稳的,机器资源也没爆,业务却“默默地”开始异常了,接口响应时间飘了,用户投诉“经常打不开”,而你啥监控都没响?没有告警,不代表没问题。你以为一切 OK,其实只是你盯错了东西。

我们监控 CPU、内存、磁盘 IO,是因为那“看得见”;可服务真正的体验,有时候是“看不见的血”,你不看错率、不看接口响应,不去感知错误率飙升,用户崩溃了,你还在图表里找“瓶颈”……

所以,今天我们不聊资源占用,也不聊系统负载。我们来聊一件更隐蔽、更容易被忽视、但足够致命的运维盲点——错误率监控与自定义告警,用 Prometheus + Alertmanager 玩出点实用又狠的东西。


错误率为什么这么难监控?

如果你问 10 个运维工程师“怎么判断服务出问题了”,起码有一半会告诉你“CPU飙了”“连接数爆了”“超时多了”。

可你问他们“怎么判断一个接口错误率异常”,他们多半会回答:“看日志吧?”

是不是突然有点空?就像你请保安盯着每个角落,却没人盯摄像头里有没有人闯进来。错误率,尤其是业务错误率,常常游离于常规监控之外。

这玩意儿难在哪?

❌ 系统指标不等于业务健康

Prometheus 默认抓的是系统层级指标,比如 node_cpu_seconds_total,你能看到负载高不高,但你看不到 /api/pay 是不是 10 次有 3 次返回了 500。

❌ 日志采集延迟/丢失严重

靠日志告警?得了吧,要 ELK 没 ELK,Logstash 卡成狗,ES 一满就掉线,日志量一大就漏数据。你连“有多少请求是 5xx”都说不准,还告警?

❌ 错误的“阈值思维”

很多人会设定“错误数 > 100 就报警”,听起来合理?不一定。你总请求数是 10w,100 个错压根不算啥;你今天上线了新接口,请求总数才 300,出 10 个错就该炸锅了。

所以光靠绝对值,是瞎报警。我们真正要看的,是 错误率趋势变化 + 自定义上下文条件


先问自己:你到底想监控什么“错”?

“错误”是个玄学词,不同业务环境下的含义完全不一样。你得先定义“什么是错”:

  1. HTTP 状态码错误(最常见)
    • 比如 5xx(服务器错)、4xx(用户错)但不报警
  2. 业务语义错误(比如返回码是 200,body 却说失败)
    • 这个得靠埋点或日志处理
  3. 接口超时/延迟超过阈值
    • 虽然没错,但“慢”有时候比“错”更致命

我们本篇聚焦第一个:HTTP 状态码错误监控告警,这是最易落地、最通用、也最具代表性的开始。


Metrics 怎么来?不要一开始就 Prometheus,先让你的服务“会说话”

Prometheus 本身不会帮你“抓”错误,它只是个“听话的人”——你得让服务先说出来。

Go 服务举个例子

用 Prometheus 官方推荐的 promhttp 中间件即可:

go
http.Handle("/metrics", promhttp.Handler())

然后你用 http_requests_total 这类指标暴露:

go
http_requests_total{status="200", method="GET", handler="/api/v1/users"}
http_requests_total{status="500", method="GET", handler="/api/v1/users"}

重点是你要把 status 标签挂出来,它是你做错误率计算的关键维度。

Nginx 怎么搞?

打开 stub_status?那只能看到连接数。

你得用 nginx-vts-exporter 或者 nginx-prometheus-exporter,配合下面的 log_format 输出:

nginx
log_format prometheus '$remote_addr - $remote_user [$time_local] ''"$request" $status $body_bytes_sent ''"$http_referer" "$http_user_agent"';

然后你就能拿到请求数与状态码统计数据。


PromQL 怎么写?别再只会 count() 了兄弟

我们来看一个真实例子。

🔢 目标:每5分钟内,5xx比例 > 5%,告警

步骤1:错误率 PromQL 公式

promql
sum(rate(http_requests_total{status=~"5.."}[5m])) 
/ 
sum(rate(http_requests_total[5m]))

是不是很眼熟?这是最常见的“错误率”计算方式,注意用了 rate 表示每秒速率,5分钟滑窗平均。也就是说过去5分钟里,错误比例是多少。

步骤2:把它写成告警规则

yaml
groups:
- name: errorsrules:- alert: HighHttpErrorRateexpr: |sum(rate(http_requests_total{status=~"5.."}[5m]))/sum(rate(http_requests_total[5m])) > 0.05for: 1mlabels:severity: warningannotations:summary: "接口错误率过高"description: "5xx 错误比例过去5分钟超过5%"

注意 for: 1m 表示这个条件要持续满足1分钟才会触发,防止抖动误报。


更进一步:支持不同接口分开告警

你不可能用一个告警规则监控所有接口,不然 GET /favicon.ico 报错都报警,那不疯了吗。

你可以用 group by handler

promql
sum(rate(http_requests_total{status=~"5.."}[5m])) by (handler)
/ 
sum(rate(http_requests_total[5m])) by (handler)

这样每个接口都有自己的错误率统计。

但这时候问题来了:你会报警太多。

那怎么解决告警泛滥?

有三种方法:

  1. 过滤 QPS 太低的接口
  2. promql
  3. sum(rate(http_requests_total[5m])) by (handler) > 0.5 意思是只告警那些 5 分钟请求数 > 150 的接口
  4. 增加重复抑制(inhibit rules) Alertmanager 支持同类型告警合并,比如: yaml
  5. inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['handler']
  6. 添加 error_budget 思维 将阈值动态调整,比如允许某接口每天 0.1% 错误率,一旦超出就告警,而不是死板写死 5%。


可视化监控:用 Grafana 展示错误率趋势

别让 Alertmanager 变成“报警黑匣子”,我们需要用图表告诉别人“错在哪”“什么时候开始错的”“错了多久”。

推荐的 Dashboard 模块:

  • 错误率时间序列曲线
  • Top N 错误率接口排行
  • 按 status_code 维度展示错误分布
  • 最近一次告警时间 / 处理状态(从 Alertmanager webhook 拿)

配合 grafana-image-renderer 插件,你甚至可以把这张图嵌入邮件或飞书告警里,视觉直观。


高阶玩法:加上 SLIs 和 SLOs 思维

传统监控关注“异常”,SRE更关注“用户体验”。所以我们可以借助 Google SRE 提出的 SLI/SLO 框架,将错误率与“服务可用性”绑定。

举个例子:

  • 你承诺 API 月可用性 99.9%,每天最多允许错误请求数 = 请求总数 * 0.001
  • 那么你就可以计算:今天用了多少 Error Budget?

promql
(sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))) > 0.001

这类告警可以改为“趋势型”,而不是“事件型”告警。


告警了,然后呢?别光响不处理!

最后别忘了,告警只是起点,不是终点。

一个真正成熟的错误率监控系统,应该包括:

  • 自动判断根因(比如 5xx 是否只集中在某个接口)
  • 自动关联代码版本(是否刚刚部署)
  • 自动生成工单或发送飞书通知
  • 可选静默机制(比如发布窗口不报警)

而这,都可以通过 Prometheus + Alertmanager + Webhook + CI/CD 工具 + 可观测平台(如 Grafana Loki、Jaeger)来完成闭环。


你以为你没问题,可能只是你还没看见问题。错误率不是挂了才算错,用户点个按钮卡3秒转圈圈也可能直接卸载你 App。Prometheus 能不能告诉你“服务还活着”很容易,能不能告诉你“用户爽不爽”,就看你有没有定义出属于你自己的告警标准。

别再等线上炸锅了才后悔没加告警,尤其是这种“不炸但持续渗血”的错误率。

说到底,你监控的是数字,但你要保障的是体验。

http://www.dtcms.com/a/286833.html

相关文章:

  • 【Linux】Linux异步IO-io_uring
  • YOLO融合CAF-YOLO中的ACFM模块
  • 怎么解决Spring循环依赖问题
  • go安装使用gin 框架
  • 在Jetson部署AI语音家居助手(二):语音激活+语音转文字
  • RS485转PROFIBUS DP网关写入命令让JRT激光测距传感器开启慢速模式连续测量
  • Angular项目IOS16.1.1设备页面空白问题
  • Windows 环境下递归搜索文件内容包含字符串
  • 亚马逊广告高级玩法:如何通过ASIN广告打击竞品流量?
  • 关于一个引力问题的回答,兼谈AI助学作用
  • 读书笔记:《动手做AI Agent》
  • el-date-picker 如何给出 所选月份的最后一天
  • C++ -- STL-- stack and queue
  • 通付盾即将亮相2025世界人工智能大会丨携多智能体协同平台赋能千行百业
  • 如何写python requests?
  • [Linux]如何設置靜態IP位址?
  • LangChain 源码剖析(七)RunnableBindingBase 深度剖析:给 Runnable“穿衣服“ 的装饰器架构
  • Vuex 基本概念
  • Java HashMap高频面试题深度解析
  • Redis高频面试题:利用I/O多路复用实现高并发
  • 在java后端项目中,controller、dal、service的作用是什么?
  • 从 0 安装 Label Studio:搭建可后台运行的数据标注平台(systemd 实践
  • 微服务项目总结
  • 【c++】中也有floor函数吗?他与JavaScript中的floor有啥区别?
  • 【iOS】消息传递和消息转发
  • Ubuntu系统下快速体验iperf3工具(网络性能测试)
  • CAN通信静默模式的原理与应用
  • 【JAVA】JVM内存泄漏围剿终极指南:Arthas在线诊断 + MAT内存分析完整链路
  • 代码随想录算法训练营第二十四天
  • 中国工业RFID前三品牌