别再只盯着CPU和内存了:用Prometheus + Grafana把业务真正跑起来的样子画出来
大家好,我是Echo_Wish。
干运维这些年,我见过太多团队把监控做成了“机器体检报告”。CPU红了就报警,内存高了就扩容,磁盘满了就清理。看起来很专业,结果业务出问题的时候,大家还是一脸懵:用户到底卡在哪一步?支付成功率掉了多少?哪个接口把整个链路拖死了?
监控如果只盯着基础设施,那就永远是“事后诸葛亮”。真正有用的,是把业务链路端到端地可视化出来——从用户点开页面,到接口调用,再到数据库、缓存、消息队列,最后到业务结果,整条链路清清楚楚。
今天我就用Prometheus + Grafana,带你把这套东西真正落地。不是讲概念,是直接给你能跑的示例。
先想清楚:你到底要监控什么?
很多人一上来就装Exporter、写查询,结果仪表盘越堆越乱。我的建议是反过来:先问自己三个问题。
- 用户最关心的业务结果是什么?(下单成功、支付完成、内容加载)
- 这个结果依赖哪几条关键路径?
- 哪几个数字掉了,会立刻影响收入或体验?
把这三个问题答清楚,你要采集的指标自然就出来了。不要一开始就追求“全量”,先把核心业务链路画清楚。
我个人的习惯是:先画一张业务流程图,再在图上标出需要打点的地方。这样Prometheus里的指标才有意义,Grafana的面板也不会变成数字堆砌。
架构很简单,关键在“业务指标”
技术栈就三样:
- 业务服务自己暴露
/metrics(用Prometheus client库) - Prometheus负责拉取和存储
- Grafana做查询和可视化
重点不是装多少Exporter,而是业务代码里主动上报有意义的指标。
下面用一个简化的电商下单接口举例。假设用Go写(其他语言差不多,思路一样)。
package main
import (
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
orderTotal = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "business_order_total",
Help: "下单请求总数",
},
[]string{
"status", "channel"},
)
orderDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "business_order_duration_seconds",
Help: "下单接口耗时",
Buckets: []float64{
0.05, 0.1, 0.2, 0.5, 1, 2, 5},
},
[]string{
"status"},
)
paymentSuccess = prometheus.NewCounter(
prometheus.CounterOpts{
Name: "business_payment_success_total",
Help: "支付成功次数",
},
)
)
func init() {
prometheus.MustRegister(orderTotal, orderDuration, paymentSuccess)
}
func createOrderHandler(w http.ResponseWriter, r *http.Request) {
start := time.Now()
status := "success"
channel := r.URL.Query().Get("channel")
if channel == "" {
channel = "app"
}
// 模拟业务逻辑
// ... 校验库存、创建订单、调用支付 ...
// 假设支付成功
paymentSuccess.Inc()
orderTotal.WithLabelValues(status, channel).Inc()
orderDuration.WithLabelValues(status).Observe(time.Since(start).Seconds())
w.Write([]byte(`{"code":0,"msg":"ok"}`))
}
func main() {
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/order/create", createOrderHandler)
http.ListenAndServe(":8080", nil)
}
这段代码做了三件事:
- 记录下单总量(带状态和渠道)
- 记录耗时分布
- 单独记支付成功数
有了这些,你就可以算成功率、P99耗时、不同渠道的转化差异。这比单纯看CPU有用多了。
Prometheus这边怎么配
配置很常规,但有个细节我强烈建议做好:按业务而不是按机器分组。
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'business-order'
static_configs:
- targets: ['order-service-1:8080', 'order-service-2:8080']
metrics_path: /metrics
relabel_configs:
- source_labels: [__address__]
target_label: instance
如果你用K8s,建议直接用ServiceMonitor或者Pod注解,让Prometheus自动发现。手动写targets很快就会崩溃。
另外,别把所有指标都默认拉15秒一次。高频业务可以更密一点,低频的可以拉长。资源是有成本的,尤其是Histogram。
Grafana仪表盘怎么设计才不瞎
很多人的Grafana面板是“指标堆砌”,看起来很满,实际看不出问题。我推荐按业务视角分层:
第一层:业务结果总览
- 今日下单量
- 支付成功率
- 核心接口P99
- 错误率
用大数字(Stat)+ 趋势线(Time series)就够了。
成功率可以这样算:
sum(rate(business_payment_success_total[5m]))
/
sum(rate(business_order_total{status="success"}[5m]))
第二层:链路拆解
把下单链路拆成几个阶段:创建订单 → 库存校验 → 支付 → 通知。每个阶段单独看耗时和失败率。这样出问题的时候,一眼就能定位是哪个环节慢了。
第三层:渠道和版本对比
不同渠道(App、小程序、H5)、不同版本的成功率、耗时差异。很多“突然变慢”其实是某个渠道或某个灰度版本出了问题。
我个人有个小习惯:每个重要面板都加一个“业务影响说明”。比如成功率掉到99%以下时,旁边直接写“预计影响订单量约X单/小时”。这样值班的人看到数字,马上知道严重程度,而不是还要再算一遍。
几个容易踩的坑
指标命名太随意
后来你会发现查都查不出来。建议统一前缀,比如business_开头,标签尽量少而准。Cardinality爆炸
别把用户ID、订单号这类高基数东西塞进标签。Prometheus会直接被打爆。高基数用日志或者专门的链路追踪系统。只看平均值
平均值会骗人。一定要看分位数(P95、P99),再配合成功率。仪表盘没有“故事线”
好的仪表盘是有阅读顺序的:先看结果,再看链路,最后看细节。不要一上来就甩几十个图。
写在最后
Prometheus + Grafana本身不难,难的是你有没有真正站在业务的角度去想“用户到底卡在哪”。
很多团队监控做得很全,业务一出问题还是靠“感觉”和“猜”。根子在于监控对象错了。机器指标是基础,但真正能让你晚上睡得着的,是那些直接反映业务健康的数字。
我自己现在做新系统,第一件事不是先装Node Exporter,而是先跟产品、开发一起把核心业务指标定义清楚。这个习惯帮我省了无数次半夜被叫醒后的无效排查。
监控不是装一堆工具,而是把“业务正在发生什么”这件事,用数字和图表讲清楚。
你最近有在做业务监控相关的改造吗?或者手头有哪个指标怎么也算不准的,欢迎直接丢出来聊聊。