Sentinel 这个名字,做后端流量治理的人应该都不陌生。我接手过不少微服务项目,几乎所有带点规模的系统都会引入它做限流熔断。但很多团队用 Sentinel 只停留在接入兜底异常这一步,控制台上看一眼 QPS、Block 数,线上真出问题的时候,还是两眼一抹黑——控制台看实时数据还行,想回看过去一小时某次峰值前后的曲线、想把限流情况和业务黄金指标放在同一个大盘里比对,就抓瞎了。
这个项目标题说得很直接:把 Sentinel 的监控数据接入 Prometheus,然后用 Grafana 统一展示 QPS、RT、Block 数。我的第一反应是,总算有人把这块平时最容易被忽视的短板补上了。接入本身不算难,难的是指标口径选对、PromQL 写对、面板字段设计得能真正指导调参。这篇就把我从头到尾踩过的坑、调过的配置、验证过的查询语句,完整摊开来讲。
1. 整体方案设计与数据链路拆解
1.1 为什么要抛弃控制台、走 Prometheus 这条路
自带的 Sentinel 控制台确实能看实时指标,但它几个硬伤在稍微有点规模的环境下非常难受。
首先是数据留存。默认的 8080 控制台通过接口从应用拉取实时数据,页面切走了、时间过了,数据就没有了。想复盘一次大促前的压测数据,或者排查凌晨某次限流误伤,控制台基本给不了线索。其次是多维度关联,Sentinel 管理的是资源维度(比如某个接口、某个方法)的流量和阻断情况,但你真正定位问题时,往往需要把 Sentinel 的指标和业务系统的 QPS、机器负载、GC 压力放在一起看。控制台做不到这种跨系统的关联。第三是多集群聚合,多个应用、多台机器的指标在控制台里看很不直观,而 Prometheus + Grafana 天生就是干这个的。
所以这个项目的本质,就是把 Sentinel 从"实时报警器"升级成"可追溯、可对比、可分析"的监控体系。资源维度统一交给 Prometheus 聚合,展示交给 Grafana,Sentinel 本身只负责产数据。
1.2 数据链路的四个环节
整个链路非常清晰,核心数据流如下:
应用内部 Sentinel 埋点 ↓ Sentinel 的 Prometheus 适配器暴露 /metrics 端点 ↓ Prometheus Server 按间隔拉取并存储 ↓ Grafana 配置数据源、渲染面板这个链路里有几个关键点需要提前想清楚。
Sentinel 的指标适配器不是默认开启的,需要引入额外的依赖并做初始化配置。它内部通过 Sentinel 的 MetricScheduler 周期性将当前窗口内的统计值推到注册的 Collector 上,再由采集器暴露给 Prometheus。简单理解,就是 Sentinel 自己维护一套滑动窗口计数,适配器负责把计数翻译成 Prometheus 的指标格式。
另一个重要决策是 Prometheus 的拉取方式。绝大多数场景下采用 Prometheus Server 主动拉取即可,也就是 static_configs 配置目标地址。但如果应用是短生命周期任务,或者机器 IP 经常漂移(比如容器平台重建),那就要考虑用 Prometheus 的服务发现能力,或者走 Pushgateway 推模式。我在实际项目中见过不少把 Pushgateway 用成主力的,最后 Pushgateway 单点挂了全部监控断掉,非常难受,所以优先建议拉模式。
1.3 选型对比:Sentinel 监控方案的三条路线
既然要做 Sentinel 指标可视化,实际可选的不止这一条路,我把三种路线摆出来对比一下,大家按自己环境选。
| 方案 | 数据链路 | 优点 | 缺点 |
|---|---|---|---|
| 控制台直连 | 应用 -> 控制台实时拉取 | 部署简单、零额外开发 | 无历史数据、单点依赖、无法与业务指标联动 |
| Prometheus 拉模式 | 应用暴露 metrics -> Prometheus 拉取 | 标准生态、留存完整、易于关联与告警 | 需引入适配器、需配置文件 |
| Prometheus 推模式 | 应用上报 -> Pushgateway -> Prometheus | 适合短任务、绕过网络限制 | 增加中间组件、指标语义受限、易成瓶颈 |
单机单应用做 Demo,控制台够用。但一旦上了多实例或微服务,Prometheus 拉模式几乎是唯一合理的选择。它跟 Sentinel 官方在监控埋点上推荐的方向也保持一致,后面生态扩展(比如接告警、接 Exporter 自监控)都是顺手的事。
2. 核心细节解析:Sentinel 指标适配器与指标口径
2.1 依赖引入与初始化,这一步很多人栽跟头
Sentinel 官方的 Prometheus 适配器在 Sentinel 的扩展包中,用 Maven 的话配置一下就能拿到:
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-prometheus-metric-exporter</artifactId> <version>1.8.7</version> </dependency>这里特别提醒一点,版本必须跟你项目里的 sentinel-core、sentinel-annotation-aspectj 保持一致。我在一个老项目上遇到过 sentinel-core 还是 1.8.0,适配器却是 1.8.7 的情况,启动时直接报 NoSuchMethodError,排错花了小半天。建议在项目里用一个属性统一管理 Sentinel 相关版本。
依赖引入之后,还需要显式初始化注册中心,因为适配器需要知道把指标暴露在哪个端口。常见的做法是在应用启动时加一段:
@PostConstruct public void initSentinelPrometheus() { MetricExporter exporter = new PrometheusMetricExporter(); exporter.init(); }PrometheusMetricExporter 默认会开启一个独立的 HTTP 端口暴露指标。初始化完成后,启动应用,访问对应的 /metrics 端点,就能看到以 sentinel_ 开头的指标。这一步如果忘了,应用起来了但 /metrics 没有数据,十有八九就是没调用 init,适配器没有被加载。
2.2 指标类型与口径,PromQL 写错全是因为没搞懂这些
适配器暴露出来的指标,在实际使用中大家最关心的是下面这几个:
| 指标名 | 类型 | 含义 |
|---|---|---|
| sentinel_metric_pass_total | Counter | 通过的请求总数 |
| sentinel_metric_block_total | Counter | 被 Sentinel 阻断的请求总数 |
| sentinel_metric_rt_milliseconds | Summary | 响应时间分布,通常带 _sum 和 _count |
| sentinel_metric_exception_total | Counter | 业务异常总数 |
很多人第一眼看着觉得挺清楚,但真正写 PromQL 的时候就蒙了。QPS 明明是每秒的指标,为什么这里只有 Counter?其实这正是 Prometheus 的设计哲学:存储层只存累加值,查询层通过 rate() 函数算速率,兼顾精度和性能。
所以计算某个资源的 QPS 不能直接查 sentinel_metric_pass_total,要看一秒钟窗口内的增量。正确写法是:
sum(rate(sentinel_metric_pass_total[1m])) by (resource)这个查询表达的意思是,取最近一分钟内每秒平均增长量,再按资源维度汇总。同理 Block 的数量:
sum(rate(sentinel_metric_block_total[1m])) by (resource)RT 的处理有一些特殊性。sentinel_metric_rt_milliseconds_sum 是所有请求 RT 的总和,_count 是请求次数,平均 RT 就是两者相除:
sum(rate(sentinel_metric_rt_milliseconds_sum[1m])) by (resource) / sum(rate(sentinel_metric_rt_milliseconds_count[1m])) by (resource)这里有个细节值得留意:除法两边必须用同样的 by 条件聚合,粒度不一致会出现维度错位,出来的数据没法看。
2.3 为什么说 Summary 而不是 Histogram
Sentinel 适配器默认输出的是 Summary 类型,不是 Histogram。这两者的核心区别在于:Summary 的百分位计算在客户端完成,Prometheus 端只拿着现成的分位数;而 Histogram 是服务端计算分位数,但在聚合多个实例时存在一定误差。因为适配器采用 Summary,我们在 Grafana 里直接查 sentinel_metric_rt_milliseconds{} 就能看到多分位的 RT 数据,省去了一堆 bucket 的处理。代价是你没法像 Histogram 那样跨实例精确聚合分位数,生产环境建议把资源维度尽量拆细,让单个资源的统计尽量落在单实例内部闭环。
2.4 指标还带了哪些 Label,别只盯着 QPS
除了资源维度,Sentinel 的指标还带上了 type、origin、resource 等标签。type 主要区分调用类型(比如入口流量还是内部调用),resource 就是你在代码里 @SentinelResource 指定的资源名。
我在实际应用中还有一个心得:资源命名本身也是监控设计的一部分。接口资源建议用固定格式,比如 /api/order/create,不要在上面拼参数或者机器 IP。命名一乱,后续所有按 resource 聚合的查询都会失效,Grafana 面板上全是碎片化的条目,等于监控白做。
3. 实操过程:Prometheus 接入与 Grafana 面板搭建实录
3.1 Prometheus 侧配置,拉取间隔与超时设置
Prometheus 的配置通常都是 prometheus.yml。针对 Sentinel 的指标采集,最关键的一段就是 scrape_configs。直接看参考配置:
scrape_configs: - job_name: 'sentinel-metrics' metrics_path: '/metrics' scrape_interval: 15s scrape_timeout: 10s static_configs: - targets: - '192.168.1.10:9899' - '192.168.1.11:9899' labels: app: 'order-service'几个参数需要解释清楚。scrape_interval 是拉取间隔,设成 15s 是监控一个微服务常规的取值。如果发生限流的时间窗口非常短(比如 1 秒就结束了),15s 的拉取可能刚好错过峰值,导致 Grafana 上 Block 曲线看起来平缓,跟实际情况有出入。这种情况下可以把间隔缩短到 5s,代价是存储量变大,Prometheus 内存开销提高,需要做一次取舍。
scrape_timeout 必须小于 scrape_interval,否则 Prometheus 拉取没有结束新一轮又开始了,日志里会频繁刷 "context deadline exceeded"。常见配置是 interval 15s,timeout 10s,留足余量,避免业务瞬时变慢导致 metrics 端口响应超时。
metrics_path 默认是 /metrics,如果适配器暴露的路径做过修改,这里要对应调整。targets 里面写的是应用所在机器的 IP 加暴露端口。注意 Sentinel 适配器的默认暴露端口通常是 9899,但不同版本或者显式指定过端口的话会有差异,到时候以实际启动日志为准。
修改完配置,需要重启 Prometheus 或者用热加载接口:
curl -X POST http://localhost:9090/-/reload然后就能在 Prometheus 的 Target 页面看到这个 job 的状态了。UP 表示采集正常,否则会显示 DOWN,同时能看到具体的错误信息,这是调监控的第一步。
3.2 快速验证指标数据,追求稳而不盲
Prometheus 配好之后,不要急着去搭 Grafana,先在 Prometheus 页面的 Graph 查询框里跑几条 PromQL,确认数据有且指标正确。
我想确认一个接口的实时 QPS,就用:
sum(rate(sentinel_metric_pass_total[1m])) by (resource)如果这个查询有数据返回,说明链路已经通了。Block 数同理:
sum(rate(sentinel_metric_block_total[1m])) by (resource)这一步看着简单,但我建议所有人别跳过去。因为在 Prometheus 层验证数据,能隔离问题源头到底是采集没生效还是展示端配置错了。直接在 Grafana 里折腾半天,最后发现 Prometheus 里就没数据,白白浪费时间。
3.3 Grafana 数据源接入与核心面板设计
Grafana 接入 Prometheus 数据源在界面上就能完成。重点说一下面板设计,这步很多人不重视,结果搭出来一张大盘没人愿意看。
我设计的思路是三个核心维度必须一眼能看清:
维度一:整体流量态势
一个 Time series 面板做总 QPS,按资源维度做叠加或堆叠展示。这样系统流量波动、哪个接口的流量占大头,一秒钟就能判断。
维度二:限流事件分布
Block 数单独做一个面板,而且建议把 QPS 和 Block 数叠加在同一个面板里面。我在实际排障时发现,只单独看 QPS 或者单独看 Block 数都非常难定位问题。必须把这两个曲线放在一起,才能回答"过载之前有没有先触发限流""限流之后流量有没有被打下去"这类关键问题。
叠加的查询写法:
sum(rate(sentinel_metric_pass_total[1m])) by (resource)sum(rate(sentinel_metric_block_total[1m])) by (resource)两个 Query 放进同一个面板,分别用不同颜色。加一个图例,一眼看两块曲线的关系。
维度三:响应时间分布
RT 面板单独一屏或一个独立分区。推荐同时展示平均 RT 和 TP99,因为两者的差距最能暴露长尾问题。我之前排查过一个问题,某个接口平均 RT 只有 80ms,但 TP99 已经到 600ms,单看平均完全没有发现,只有同时展示 TP99 才暴露出来。
TP99 的查询写法取决于 Sentinel 指标中的分位标签。如果指标里带 le="0.99" 或者 ph="99",可以这样写:
histogram_quantile(0.99, sum(rate(sentinel_metric_rt_milliseconds_bucket[1m])) by (le, resource))但要注意由于适配器是 Summary 类型,分位查询可能直接查已有标签更快,不用 histogram_quantile。两个思路大家可以根据实际指标结构选一个。
Grafana 面板的布局建议是:最上面一行放总览级指标——整个应用的总 QPS、总 Block 数、平均 RT;第二行按核心资源逐个列出 QPS、Block、RT;第三行放机器维度的系统指标(CPU、内存、GC),方便将系统压力与 Sentinel 行为联动。这样从上往下的阅读逻辑,就是"整体 -> 资源 -> 系统"层层下钻。
3.4 告警规则怎么配,限流不只是曲线上的事
Grafana 面板毕竟靠人盯,告警才是自动化兜底。一般建议在 Prometheus 侧配告警规则,常见的是以下两个方向。
一个是 Block 突增告警。Block 数突然飙升,通常不是什么好事,要么流量涌进来被挡,要么规则配置错误限制了正常流量:
groups: - name: sentinel-alerts rules: - alert: SentinelBlockSpike expr: sum(rate(sentinel_metric_block_total[1m])) by (resource) > 100 for: 2m labels: severity: warning annotations: summary: "资源 {{ $labels.resource }} Block 数异常"另一个是 RT 阈值告警,适用于核心接口有明确的 SLA 要求:
sum(rate(sentinel_metric_rt_milliseconds_sum[5m])) by (resource) / sum(rate(sentinel_metric_rt_milliseconds_count[5m])) by (resource) > 500多提一句,告警阈值千万不要拍脑袋。Block 告警阈值可以先观察一周基线数据,取平时峰值的 2~3 倍再设置。否则刚上线第一天,告警风暴先把人打懵,后面大家看到告警都选择忽略,那就完全失去意义了。
4. 常见问题与排查技巧实录
4.1 指标一直出不来,从四个方向排查
Sentinel 指标在 Grafana 里完全没有,是最常见的问题。按照以下顺序排查,基本都能解决。
先确认 Sentinel 适配器有没有被初始化。启动日志里搜 "Prometheus metric exporter" 或类似关键字,没有出现就直接看初始化代码路径。很多时候是只引入了依赖,没有调用 init 方法。
再确认暴露的端口有没有被防火墙或者容器网络策略拦截。在应用所在机器上直接 curl 一下:
curl http://localhost:9899/metrics | head -50如果本机能通,服务器之间不通,那问题大概率在网络策略上。如果 Prometheus 和 Sentinel 不在同一个网络命名空间(比如容器部署),还要检查 service 的暴露方式。
第三个排查点是 Prometheus 配置里的 targets。如果 Prometheus Target 页面显示 DOWN,点开能看到具体错误信息。常见的错误要么是连接被拒,要么是端口不通。如果是 4xx,可能是 metrics_path 不对。如果是 5xx,可能是应用端适配器挂了。
最后一个隐藏坑:多实例部署时,如果不同实例的 resource 命名不一致,Prometheus 聚合产生的 label 数量会非常多,会拖慢查询速度,甚至导致面板加载很慢。这个问题我在一个老项目上遇过,资源名有的是 /order/create,有的是 /api/order/create,两个名称都出现在面板上,后面花了不少时间统一。
4.2 Block 数是 0,但确实有限流发生
这也是一个高频问题,而且很容易误判。首先要确认 Block 指标监控的是明确的限流事件,而不是熔断降级等其它类型的拒绝。Sentinel 中 Blocked 主要对应 FlowException,也就是流控规则触发产生的拒绝。如果走的是降级(DegradeException)或者系统保护(SystemBlockException),它们会归到别的类别,不会完全体现在 Block 指标里。
另外,如果 Block 数确实有在控制台显示,但 Prometheus 里没有,大概率是拉取间隔太长错过了短时限流。这类情况下,有两种调整方向:一是把 scrap_interval 从 15s 缩短到 5s,二是把限流规则的统计窗口适当加长,让指标在时间轴上更宽一些。具体用哪种,需要看业务容忍度,我一般优先调短拉取间隔,因为规则窗口关系到限流效果本身,不该为监控绑架了业务。
4.3 RT 显示 NaN 或为 0,除法除法的精髓
RT 面板显示 NaN,绝大多数原因是 _count 分母为 0。资源在查询窗口内没有任何请求,rate 之后自然得 0,除数为 0 就会得到 NaN。对策是用 Grafana 的 reduce 函数把空值处理一下,或者在数学表达式里做空值保护。
PromQL 里可以这么处理:
sum(rate(sentinel_metric_rt_milliseconds_sum[1m])) by (resource) / clamp_min(sum(rate(sentinel_metric_rt_milliseconds_count[1m])) by (resource), 1)clamp_min 可以把分母的最小值钳制到 1,避免 NaN 出现。但注意这只影响展示,不会改变已有数据的真实性。
4.4 数据有了,但面板数值对不上控制台
有时候控制台显示 QPS 是 300,Grafana 显示 280,对不上的时候先别怀疑采集有问题,大概率是时间窗口不同。控制台显示的是秒级瞬时值,Prometheus 里 rate(x[1m]) 算的是最近一分钟的每秒平均速率。如果这一分钟刚好经历了一个短促的尖峰,两边的读数自然不同。
所以做对比时,需要在同一时间尺度下对齐。更重要的认知是,Prometheus 的监控指标主要服务于长期趋势和告警,不是精确的业务计数。接 Sentinel 指标时,大家都应该把预期调整为"看趋势和相对变化",而不是绝对精确。
5. 面板优化的关键思路与告警联动实践
5.1 别做监控面板的千篇一律派
Graph 大面板是 Grafana 最常用的形式,但不是所有指标都适合放在折线图里。Block 数这种偶尔出现次数的指标,有时候用 Stat 面板更清晰——直接显示当前值、最近一小时总和,再配一个 Sparkline 显示趋势,一眼就知道有没有异常。
QPS 和 RT 则用 Time series。RT 分布可以再加一个 Bar gauge 面板按资源排序,方便快速定位哪个资源拖慢了整体,这种视图比看密密麻麻的曲线直观很多。
我在做面板时有一个自己的规则:如果一个面板查看时超过 3 秒才能看出结论,说明设计不合理。所有数据都应该让人在"秒级"做出判断,否则监控面板就是摆设。
5.2 多资源维度如何用模板变量提升复用性
手上有十几个微服务的时候,不要每个服务都建一套相同的面板。用 Grafana 的模板变量,可以做一个通用面板,根据下拉框切换服务名或资源名。
变量定义方式是新建一个变量 resource,查询语句:
label_values(sentinel_metric_pass_total, resource)这样下拉框就能动态列出当前所有资源名。面板里的查询,把写死的 resource 替换成 $resource。比如:
sum(rate(sentinel_metric_pass_total{resource="$resource"}[1m]))这套方案对于新服务上线非常省事:不用一行一行建面板,直接把新服务捡到同一套面板下面展示。
5.3 告警与限流策略联动,把监控闭环跑起来
其实这才是这个项目最有延展性的地方。监控不只是用来看,更应该是闭环的一个输入。我在一个项目里做过这样的联动:Prometheus 的 Block 告警触发后,Webhook 通知到一个简单的规则管理服务,该服务可以自动调整 Sentinel 的限流阈值,让集群在高峰期自动扩容流控力度。虽然整个自动化逻辑很多团队不一定需要,但"告警 -> 定位 -> 调整规则 -> 效果验证"这个闭环思路是通用的。
面板与告警是一个整体,SDK 接入只是第一步,后面如何基于指标做预案、做容量评估、做限流参数调优,才是真正把 Sentinel 价值放大的地方。
6. 落地后的几点实际体会
最后说点实际操作下来的感受。我在几个项目里把这套 Sentinel + Prometheus + Grafana 的组合搭过一遍,最大的体会是,它解决的问题不只是"能看点数据",而是把限流从一个"配置后就不管"的动作变成一个有反馈、可迭代的系统能力。没有监控的限流规则,就是盲调:规则加严了,用户受影响了都不知道,只有接口报错才能发现;规则放宽了,系统被压垮了,反应时间也可能来不及。
还有一个小技巧,Grafana 面板搭好后,建议把 URL 参数里的时间范围默认设成最近 6 小时。不要只盯着最近 15 分钟,限流问题往往跟业务高峰的时间段强相关。如果你只在出问题时才开始看面板,就已经晚了,平时多观察基线,突发异常你才有对比的依据。
资源命名的规范,也值得在项目里强调。我给团队的建议是:@SentinelResource 的资源名用"领域.动作.具体对象"的格式,比如 pay.create.order、pay.refund.order,中间不要带机器信息或动态参数。这套命名规则坚持一年下来,面板上的指标会非常整洁,聚合分析时你在按 resource 做 by 聚合会明显感觉到顺手很多。
踩过几次坑之后,我还有一个小建议:如果你的服务是多实例部署,在 Sentinel 规则的流控效果检查上,一定不要只盯着 Prometheus。单机视角下限流效果看似正常,但集群视角下流量倾斜会导致一台机器已经限流,另外一台还在硬扛。如果发现限流后系统仍然缓慢,回到面板上按 instance 标签拆分看看各实例的 QPS 分布,这一步经常能发现负载不均的隐藏问题。
监控体系的建立没有终点,把链路搭通,把面板调顺,把告警规则配准,这套组合就能在绝大多数场景下让你对系统流量状况了如指掌。后续想玩得更深,还可以把 Block 告警接到更完善的通知中枢里,把 Sentinel dashboard 从单纯的图形界面,变成真正参与系统容量治理的决策支撑。