资讯详情

资讯详情

Dubbo 在 K8s 中接入 Prometheus 监控:从指标暴露到 Grafana 面板

前几天刚把 Dubbo 服务在 k8s 里跑起来部署这块基本稳了剩下最头疼的就是监控。服务可以跑是一回事跑得好不好、有没有异常、接口响应有没有劣化这些没有数据支撑全靠猜。这篇是 Dubbo 交付系列的监控第二篇上一篇已经确认了整体监控方案走 Prometheus Grafana 这套生态这次把落地的每个环节完整走一遍。从 Dubbo 端怎么把指标吐出来到 Prometheus 怎么在集群里自动抓到这些指标再到 Grafana 怎么把数据变成看得懂的图表一步一步说清楚。如果你正在做 Dubbo 容器化改造或者想把 Dubbo 的 QPS、RT、连接数这些核心指标接到 Prometheus 体系里这篇文章应该能帮你省不少事。1. 为什么最终选了 Prometheus 这套方案而不是 Dubbo 自带的监控1.1 Dubbo 内置监控的现状和局限很多刚接触 Dubbo 的人会有一个疑问Dubbo 本身不是有 Monitor 吗为什么还要自己搭一套确实Dubbo 从很早的版本开始就提供了一个监控中心的实现服务提供方可以把调用数据上报到一个独立的 Monitor 服务然后通过它的 Web 界面查看默认端口是 8080上报端口是 7070。这个方案在传统虚拟机部署、服务规模不大的时候是能用的。但拿到 k8s 环境里问题就很明显了。首先是数据上报的机制过重。Dubbo 内置的 Monitor 需要服务方主动往监控中心上报数据这意味着每增加一个服务副本就要建立一条上报链路上报本身还会消耗线程资源。在 k8s 这种服务实例随时可能扩缩容的架构下上报链路的管理和维护成本会变得很高。其次是展示能力太弱自带的 Web 界面只能看一些基础的统计信息没有趋势对比、没有告警、没有多维度的筛选分析对排查线上问题帮助有限。最关键的是这套内置方案没有和容器基础设施打通Pod 重建之后监控数据就断了历史数据也不会持久化保存。1.2 主流选型横向对比看清楚差异再下手当时摆在面前的有几个方向一是继续用 Dubbo 自带的 Monitor二是接 Pinpoint 或 SkyWalking 这类全链路监控系统三就是 Prometheus 这套云原生体系。三个方向我做了个简单的对比基本就明白该怎么选了。方案数据采集方式指标丰富度容器友好度运维成本Dubbo 内置 Monitor主动上报基础统计信息低需要额外部署 Monitor 服务且扩展性一般Pinpoint / SkyWalkingAgent 注入 / 链路数据采集链路追踪非常强中Agent 管理、存储组件较多偏重Prometheus Grafana自动拉取 Metrics服务运行指标全面高组件轻量图表生态强大Prometheus 这套方案最吸引我的是它的拉取模型天然适配 k8s。服务只要把指标暴露在一个 HTTP 端点上Prometheus 就能通过服务发现自动找到这些实例不需要事先知道 Pod 的 IP 和端口。这意味着服务扩缩容、节点迁移都不影响监控的连续性。再加上 Grafana 提供了非常成熟的面板生态很多现成的 Dubbo 面板可以直接导入修改省去了从零做图表的时间。选择链路追踪方案也不是说不好但链路追踪解决的是一次请求经过了哪些服务的问题而监控首先要解决的是服务当前状态怎么样的问题。两者定位不同前期先把基础监控做扎实比一上来就铺一套重型的链路系统要靠谱得多。2. Dubbo 端的指标到底怎么暴露出来这里有几个关键细节2.1 Dubbo 3.x 的 Metrics 依赖加哪个决定你能看到什么确认走 Prometheus 方案之后第一件事是让 Dubbo 服务自己先把指标吐出来。Dubbo 从 2.7 版本开始引入了基于 Micrometer 的 Metrics 模块到了 3.x 版本这套东西已经相当成熟了。核心的做法是在服务端引入一个依赖然后配置暴露的端口剩下的指标收集由框架自动完成。如果是 Maven 工程加这段依赖dependency groupIdorg.apache.dubbo/groupId artifactIddubbo-metrics-prometheus/artifactId version3.2.x/version /dependency注意版本号要和你的 Dubbo 主版本保持一致。我一开始用的是 3.0 的旧版本发现里面的指标项明显没有 3.2 版本丰富一些关键字段在旧版本里根本取不到后来对齐版本号之后才解决。这个依赖的作用是让 Dubbo 在启动时自动注册一个 Metrics 端点并且以 Prometheus 期望的格式输出数据。如果你用的是 Spring Boot 的方式接入 Dubbo情况会稍有不同。Spring Boot 的 Actuator 本身也有 Metrics 端点这里要处理好 Dubbo 指标是挂在 Actuator 下面还是独立端口暴露。我倾向于独立端口暴露原因后面会说到。独立暴露不需要额外配置Dubbo 会自动开一个 HTTP 端口前提是把这个功能启用。2.2 Metrics 端口的暴露方式别和 Dubbo 服务端口搞混这里有个非常容易踩坑的地方。Dubbo 服务本身监听一个端口用于 RPC 通信默认是 20880而 Metrics 的 HTTP 端口是另一个独立端口。很多人修改了 Dubbo 的服务端口以为 Metrics 也会跟着变其实不是。在 application.yml 或者 dubbo.properties 中有这样一个配置项dubbo.metrics.prometheus.port20889 dubbo.metrics.enabletruedubbo.metrics.prometheus.port就是 Metrics 端点监听的端口。这个端口需要单独在 k8s 的 Service 定义里暴露出来。如果没有指定默认会在 20880 以外的某个端口上监听实际测试时很不方便。我建议在项目里显式固定这个端口不要用默认值。原因很简单k8s 的 Service 和 Prometheus 的抓取配置都需要明确的端口号如果端口不固定每次部署都要去查实际监听在哪个端口自动化就无从谈起。固定成一个独立端口比如 20889后续部署配置就是确定性的不会因为环境差异出幺蛾子。2.3 指标内容都包括哪些拿到数据才知道能看什么配置完成启动服务之后访问 http://pod-ip:20889/metrics 就能看到一堆指标。Dubbo 3.x 默认暴露的指标主要分为几类QPS 类指标、RT 耗时类指标、连接数类指标、线程池状态类指标。比较常用的有这几个dubbo_provider_qps_total是服务提供方的总请求数dubbo_provider_rt_milliseconds是响应时间的分布统计dubbo_provider_thread_pool_active_count是当前活跃线程数。消费方的指标也类似前缀会变成dubbo_consumer_开头的。熟悉 Prometheus 的人都知道这种 Counter 类型的指标直接看原始值没什么意义需要配合 rate、histogram_quantile 这类函数使用。这些在后面 Grafana 面板里会用到。真正有价值的是Dubbo 把这些指标从框架层面直接暴露了出来我们不需要在业务代码里埋点就能拿到完整的服务运行数据这是这套方案最大的优势。3. Prometheus 在 k8s 里怎么配置才能自动发现所有 Dubbo 实例3.1 Prometheus 的部署方式Operator 比裸部署更省心Prometheus 在 k8s 里有两种主流部署方式一种是直接用 Deployment 跑一个单实例手动挂配置文件和存储卷另一种是用 Prometheus Operator把 Prometheus 的配置、服务发现规则用 CRD 的方式管理起来。我强烈推荐第二种。Operator 方式的好处在于它的服务发现完全自动化。裸部署时你需要在 prometheus.yml 里手动写 kubernetes_sd_configs指定要发现哪种资源、用什么标签过滤。而 Operator 引入了 ServiceMonitor 这个概念只需要声明一个 ServiceMonitor 对象告诉它你想监控哪些 Service剩下的工作由 Operator 自动生成抓取配置。扩缩容之后新增的 Pod 自动就会出现在 Prometheus 的 targets 列表里完全不需要人工干预。部署 Prometheus Operator 本身不复杂一般在 k8s 集群里用 Helm 一条命令就能装完。安装完成之后会有 Prometheus、Grafana 和 Alertmanager 三个组件如果你用 kube-prometheus-stack 这个包三个组件的配置都是完整的直接改配置就能用比自己一个个部署省一半时间。3.2 ServiceMonitor 怎么写决定了 Prometheus 能不能找到目标核心来了。要让 Prometheus 自动发现 Dubbo 服务需要先确认你的 Dubbo 服务在 k8s 里是怎么暴露的。我当时的服务是一个标准的 Deployment通过 Service 暴露端口。因为 Dubbo 是 RPC 服务不需要对外提供 HTTP 访问所以 Service 类型用的是 ClusterIP只让集群内部可以访问。ServiceMonitor 配置是这样的注意重点看 selector 和 endpointsapiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: dubbo-monitor namespace: monitoring spec: selector: matchLabels: app: dubbo-service endpoints: - port: metrics path: /metrics interval: 15s namespaceSelector: matchNames: - default这里有几个关键点。selector 的 matchLabels 要对应 Service 上的标签不是 Service 对应的 Pod 标签。namespaceSelector 指定 Service 所在的命名空间。endpoints 里的 port 必须和 Service 定义的端口名一致Prometheus 是根据端口名去关联抓取地址的如果端口名对不上抓取会直接失败。一个容易被忽略的点是 interval 的配置。15 秒的抓取间隔对于 Dubbo 这种高频调用的服务来说足够了但如果你把 QPS 指标用于非常精细的容量规划可以考虑改成 10 秒甚至更短。间隔越短Prometheus 的存储压力越大需要根据自己的实际情况权衡。3.3 Service 的端口定义和标签一个都不能少为了让上面这个 ServiceMonitor 生效你的 Service 定义必须满足两个条件。第一个是端口名称要和 ServiceMonitor 里写的 port 一致第二个是标签要能被 selector 选中。apiVersion: v1 kind: Service metadata: name: dubbo-service labels: app: dubbo-service spec: selector: app: dubbo-pod ports: - name: dubbo-rpc port: 20880 targetPort: 20880 - name: metrics port: 20889 targetPort: 20889注意这里的 dubbo-rpc 端口如果只是集群内部服务间互相调用port 和 targetPort 保持一致就行。metrics 端口则是给 Prometheus 抓取用的。把这两个端口同时暴露出来Prometheus 就可以只通过 Service 的名称和端口关联到正确的抓取地址不会抓错端口。我遇到过一种情况Service 的 selector 配错了导致 Service 后面没有任何 Pod 端点。Prometheus 能发现这个 Service但抓取时显示连接拒绝。后来排查问题发现是标签大小写写错了Pod 的 label 是app: Dubbo-PodService 选的是app: dubbo-pod。标签大小写是敏感区一旦不一致Service 对应的端点列表就是空的。这个问题定位花了不少时间记住一个原则给 Dubbo 服务打标签的时候全部用小写后面所有配置都统一用同样的小写标签就不会有这种问题。4. 抓取配置验证与 Grafana 面板搭建数据能正常显示才叫完成4.1 验证 Prometheus 是否抓到了目标这一步别跳过配置完成之后不要急着去配 Grafana先确认 Prometheus 这边已经抓到数据。打开 Prometheus 的 Web 界面在 Targets 页面里你会看到 ServiceMonitor 自动生成的抓取任务。正常状态下这些目标的状态应该是 UP表示抓取成功。如果状态是 DOWN点进去可以看到具体报错信息。最常见的错误是连接超时或者 404。连接超时通常是因为 Service 的端口配置不对或者网络安全策略限制了 Prometheus 所在命名空间访问目标 Service。404 则是 path 不对确认 Dubbo Metrics 路径确实是 /metrics不要配成了 /actuator/metrics 或者其他路径。在 Targets 页面确认状态正常之后到 Graph 页面执行一个简单的查询比如输入dubbo_provider_qps_total如果能查到数据说明指标已经成功入库了。这里有个小技巧输入指标名之后Prometheus 会自动联想出完整的指标名这也能顺便确认 Dubbo 端到底暴露了哪些指标方便后面写 Grafana 的查询表达式。4.2 Grafana 面板的选择与修改拿到结果只是第一步Prometheus 数据到位之后Grafana 这边就简单多了。官方社区和 Grafana 网站上有现成的 Dubbo 相关面板可以直接导入搜索关键词 dubbo 或者 dubbbo 都能找到。导入的方式是在 Grafana 里通过 Dashboard ID 导入或者直接把 JSON 内容粘进去。但这里我要提醒一句现成的面板一般能覆盖 90% 的常见需求但不要指望导入之后就能完全适配你的服务。面板里的很多查询写的是sum(dubbo_provider_qps_total{...}) by (interface)这种格式其中的标签名可能需要改成你的环境里实际存在的标签。Dubbo 暴露的指标标签通常包含 application、interface、method 这些通过 Prometheus 的标签浏览器可以确认实际有哪些标签。我自己常用的做法是先导入社区面板然后到 Prometheus 里看一下实际的标签组合再回到 Grafana 的编辑界面调整查询。调整的重点主要是两个一个是用 application 标签区分不同服务另一个是用 interface 和 method 做下钻分析这样既能看全局 QPS也能定位到具体某个接口的耗时变化。这套逻辑跑通之后日常排查问题基本就够用了。4.3 几个必须加的常用图表指标覆盖日常巡检需求面板搭建的时候除了 QPS 和响应时间这两个核心指标我建议再加几个容易被忽略但实际非常有用的图。第一个是线程池活跃度对应指标dubbo_provider_thread_pool_active_count和dubbo_provider_thread_pool_queue_size这两个指标能直接反映服务是不是接近处理瓶颈。如果你在图上看到 queue_size 一直往上走说明消费速度跟不上生产速度后面迟早会出问题。第二个是连接数和连接错误数对应dubbo_provider_connection_count这些指标。连接数出现断崖式下跌往往意味着网络异常或者服务重启这个在故障排查时很有参考价值。第三个是消费方的视角加一个dubbo_consumer_rt_milliseconds的视图可以看到服务调用方的实际感受而不是只看服务端的处理时间毕竟网络开销和序列化开销也是真实存在的延迟。这些图表加完之后可以在 Grafana 里设置一个简单的自动刷新比如 30 秒日常盯在屏幕上就能感知到服务状态的变化。当然主动盯着看只是辅助手段告警规则才是真正能帮你发现问题的方式。5. 告警规则与部署中踩过的若干坑一次性整理给你5.1 告警规则怎么配才有价值避免被打扰Prometheus 的告警规则分成两部分先在 Prometheus 里写规则做判断然后通过 Alertmanager 把告警消息发出去。规则本身不复杂麻烦的是怎么设置阈值才合理。阈值设得太松告警不痛不痒设得太紧告警轰炸之后大家就麻木了反而把真正重要的问题淹没了。我建议最开始从这三个维度配置。第一个是可用性维度比如服务完全不可用持续 1 分钟都没有任何请求进来这种肯定要告警。第二个是性能劣化维度比如 TP99 响应时间持续 5 分钟超过平时的两倍这个说明服务已经出现明显的性能问题。第三个是资源耗尽维度比如线程池活跃度超过 90% 持续一段时间预示着服务即将过载。写规则的时候注意 Prometheus 的表达式语法结合 for 关键字设置持续时间可以有效过滤掉瞬时抖动。比如突然出现一个 1 秒的尖峰紧接着恢复正常这种情况 if 直接告警就是误报加了持续时间的判断之后只有问题存在一段时间才触发信噪比会高很多。告警消息的接收渠道可以用邮件和 Webhook总之要确保告警发到能及时响应的地方这比单纯展示监控面板价值大得多。5.2 抓取失败以及数据不落地的排查思路部署的过程中一定不会一帆风顺这里把最常见的几个问题集中说一下。端口配置类的问题最多。现象是 Prometheus 的 targets 状态为 DOWN看日志报连接拒绝。排查路径是先手动访问一下这个 Pod 的 IP 加端口确认 Metrics 端点本身通不通。如果不通进容器里看监听端口是不是 20889用netstat -tlnp一查就知道了。如果容器里是通的Prometheus 还是连不上检查 Service 的 targetPort 是不是指歪了有没有指向 Dubbo 的 RPC 端口。这套排查下来八成的问题都能定位。第二种常见问题是抓取到了数据但图表上没有内容。这种情况通常是指标名变了或者标签名不一样。Dubbo 3.2 和 3.0 的指标命名有差异导入旧面板之后完全可能查不到数据。遇到这种情况在 Prometheus 的 Graph 页面里敲一个dubbo_看看自动联想的结果对照实际的指标名修改 Grafana 查询即可。第三种问题是数据偶尔断档图表上出现周期性缺口。这个大概率是 Prometheus 的抓取超时时间设置得太短在 Pod 被调度到其他节点之后第一次抓取需要新建连接耗时略长超过默认的 scrape_timeout 就会导致那一次抓取失败。把抓取超时适当调大一点比如 10 秒缺口就能解决。5.3 资源开销与长期运维需要注意的细节Prometheus 这套体系跑起来之后还需要关注一下资源消耗。Dubbo 的 Metrics 端点每 15 秒被抓取一次数据量在服务数量多的时候相当可观Prometheus 的存储盘如果太小会很快吃满。建议给 Prometheus 单独挂一个足够的持久化卷同时配置合理的保留时长比如 15 天超出自动清理。Grafana 那边如果觉得加载慢检查一下面板里的查询是不是有大量全量聚合操作。比如sum(dubbo_provider_qps_total)这种不带任何标签过滤的查询在数据量大时会消耗较多计算资源。日常使用可以适当缩小时间范围减少 Grafana 拉取的数据量加载速度会明显改善。还有一个容易忽略的问题是资源请求值。在 k8s 里部署这些监控组件一定要配置 requests 和 limits。我之前遇到过监控组件被挤到内存不足然后 Pod 反复重启的情况就是因为没有设置合理的 requests调度器把它调度到了一个资源紧张的节点。给监控组件本身配置好资源限制才能保证它在任何情况下都稳定运行。6. 从这套交付过程中学到的几个实际经验整个 Dubbo 监控交付下来我最强烈的感受是监控体系的搭建费力气的不是部署组件而是把各个端点打通、把数据语义理顺。Dobbo 本身已经把框架层面的指标暴露得很完善Prometheus 生态也足够成熟真正的难度在于理解每一个配置项背后对应的网络路径和数据链路。如果你正准备动手做这件事我给的建议是先把 Metrics 端口的暴露方式和 ServiceMonitor 的标签匹配逻辑搞清楚这两个点是最容易出问题也是最影响整体链路的。然后是先抓数据后做图哪怕 Grafana 面板做得再漂亮数据链路都没通也没有什么意义。后续还可以继续扩展的方向是把 Prometheus 的数据和日志系统打通或者接入全链路追踪。监控只是第一步之后在此基础上做容量规划、做链路分析才是更大的价值所在。一步步来先把这一套跑稳。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →