Java 生态监控体系实战:Prometheus+Grafana+SkyWalking 整合全指南(二)

三、实战第二步:Java 服务监控改造(指标 + 链路)

3.1 接入 Prometheus 指标监控(基于 Micrometer)

Spring Boot 应用通过Spring Boot Actuator暴露监控端点,结合Micrometer将指标转换为 Prometheus 格式,步骤如下:

3.1.1 引入依赖(以 Maven 为例)

在所有 Java 服务(user-service/order-service 等)的pom.xml中添加依赖:

xml 复制代码
\<!-- Actuator:暴露监控端点 -->

\<dependency>

   \<groupId>org.springframework.boot\</groupId>

   \<artifactId>spring-boot-starter-actuator\</artifactId>

\</dependency>

\<!-- Micrometer Prometheus:指标格式转换 -->

\<dependency>

   \<groupId>io.micrometer\</groupId>

   \<artifactId>micrometer-registry-prometheus\</artifactId>

\</dependency>

\<!-- Micrometer Core:指标核心库 -->

\<dependency>

   \<groupId>io.micrometer\</groupId>

   \<artifactId>micrometer-core\</artifactId>

\</dependency>
3.1.2 配置 Actuator 端点

application.yml中配置暴露 Prometheus 指标端点:

yml 复制代码
spring:

 application:

   name: user-service  # 服务名(不同服务需修改,如order-service)

\# Actuator配置

management:

 endpoints:

   web:

     exposure:

       include: prometheus,health,info  # 暴露的端点(prometheus为核心指标端点)

 endpoint:

   health:

     show-details: always  # 健康检查显示详情

 metrics:

   tags:

     application: \${spring.application.name}  # 为所有指标添加"application"标签(便于按服务筛选)

   export:

     prometheus:

       enabled: true  # 启用Prometheus指标导出
3.1.3 自定义业务指标(以订单服务为例)

除了默认的 JVM、HTTP 请求等指标,实际业务中常需监控自定义指标(如订单量、支付成功率)。以order-service为例,通过MeterRegistry实现指标埋点:

  1. 定义指标枚举类(统一管理指标名称与标签):
java 复制代码
package com.example.orderservice.metrics;

/\*\*

\* 订单服务自定义指标枚举

\*/

public enum OrderMetricsEnum {

   // 订单创建总量(标签:order\_type-订单类型,status-订单状态)

   ORDER\_CREATE\_TOTAL("order.create.total", "订单创建总量", "order\_type", "status"),

   // 订单支付成功率(标签:payment\_type-支付方式)

   ORDER\_PAY\_SUCCESS\_RATE("order.pay.success.rate", "订单支付成功率", "payment\_type");

   private final String metricName;  // 指标名称

   private final String description; // 指标描述

   private final String\[] tags;      // 指标标签

   OrderMetricsEnum(String metricName, String description, String... tags) {

       this.metricName = metricName;

       this.description = description;

       this.tags = tags;

   }

   // Getter方法

   public String getMetricName() { return metricName; }

   public String getDescription() { return description; }

   public String\[] getTags() { return tags; }

}
  1. 封装指标工具类(简化指标使用):
java 复制代码
package com.example.orderservice.metrics;

import io.micrometer.core.instrument.Counter;

import io.micrometer.core.instrument.Gauge;

import io.micrometer.core.instrument.MeterRegistry;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

import java.util.HashMap;

import java.util.Map;

@Component

public class OrderMetricsUtils {

   private final MeterRegistry meterRegistry;

   // 缓存Counter指标(避免重复创建)

   private final Map\<String, Counter> counterCache = new HashMap<>();

   // 构造注入MeterRegistry

   public OrderMetricsUtils(MeterRegistry meterRegistry) {

       this.meterRegistry = meterRegistry;

   }

   /\*\*

    \* 初始化Counter指标

    \*/

   @PostConstruct

   public void initCounters() {

       for (OrderMetricsEnum metricsEnum : OrderMetricsEnum.values()) {

           if (metricsEnum.getMetricName().contains("total")) { // 总量类指标使用Counter

               Counter counter = Counter.builder(metricsEnum.getMetricName())

                       .description(metricsEnum.getDescription())

                       .tags(metricsEnum.getTags()) // 预设标签(实际使用时需传值)

                       .register(meterRegistry);

               counterCache.put(metricsEnum.getMetricName(), counter);

           }

       }

   }

   /\*\*

    \* 增加Counter指标计数

    \* @param metricsEnum 指标枚举

    \* @param tagValues 标签值(需与枚举中tags顺序一致)

    \*/

   public void incrementCounter(OrderMetricsEnum metricsEnum, String... tagValues) {

       Counter counter = counterCache.get(metricsEnum.getMetricName());

       if (counter != null) {

           counter.increment(tagValues);

       }

   }

   /\*\*

    \* 注册Gauge指标(适用于瞬时值,如当前待支付订单数)

    \* @param metricsEnum 指标枚举

    \* @param valueSupplier 值提供者(函数式接口,动态获取值)

    \* @param tagValues 标签值

    \*/

   public void registerGauge(OrderMetricsEnum metricsEnum, Number valueSupplier, String... tagValues) {

       Gauge.builder(metricsEnum.getMetricName(), valueSupplier)

               .description(metricsEnum.getDescription())

               .tags(tagValues)

               .register(meterRegistry);

   }

}
  1. 在业务代码中埋点(订单创建接口为例):
java 复制代码
package com.example.orderservice.controller;

import com.example.orderservice.metrics.OrderMetricsEnum;

import com.example.orderservice.metrics.OrderMetricsUtils;

import com.example.orderservice.service.OrderService;

import com.example.orderservice.vo.OrderVO;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController

@RequestMapping("/order")

public class OrderController {

   @Resource

   private OrderService orderService;

   @Resource

   private OrderMetricsUtils orderMetricsUtils;

   /\*\*

    \* 创建订单接口

    \*/

   @PostMapping("/create")

   public String createOrder(@RequestBody OrderVO orderVO) {

       try {

           String orderId = orderService.createOrder(orderVO);

           // 埋点:订单创建成功(标签:order\_type=普通订单,status=成功)

           orderMetricsUtils.incrementCounter(

                   OrderMetricsEnum.ORDER\_CREATE\_TOTAL,

                   orderVO.getOrderType(), "success"

           );

           return "订单创建成功,订单ID:" + orderId;

       } catch (Exception e) {

           // 埋点:订单创建失败

           orderMetricsUtils.incrementCounter(

                   OrderMetricsEnum.ORDER\_CREATE\_TOTAL,

                   orderVO.getOrderType(), "fail"

           );

           return "订单创建失败:" + e.getMessage();

       }

   }

}
3.1.4 验证指标暴露

启动user-service(端口 8081),访问 http://localhost:8081/actuator/prometheus,应能看到:

  • 默认指标:如jvm_memory_used_bytes(JVM 内存使用)、http_server_requests_seconds_count(HTTP 请求计数);

  • 自定义指标:如order_create_total{application="order-service",order_type="普通订单",status="success",...}

3.2 接入 SkyWalking 链路追踪(基于 Agent)

SkyWalking 通过 Java Agent 实现无侵入式链路采集,无需修改业务代码,只需在服务启动时挂载 Agent 包。

3.2.1 下载 SkyWalking Agent

SkyWalking 官网下载与 OAP Server 版本(9.4.0)一致的 Agent 包,解压后得到skywalking-agent目录,核心文件包括:

  • agent.config:Agent 配置文件;

  • skywalking-agent.jar:Agent 核心包。

3.2.2 配置 Agent

修改skywalking-agent/agent.config中的关键配置:

xml 复制代码
\# 1. 应用名称(必填,不同服务需修改,如user-service、order-service)

agent.service\_name=\${SW\_AGENT\_NAME:order-service}

\# 2. OAP Server地址(填写部署OAP Server的服务器IP)

collector.backend\_service=\${SW\_AGENT\_COLLECTOR\_BACKEND\_SERVICES:192.168.1.100:11800}

\# 3. 采样率(默认100%,生产环境可根据性能调整,如50%)

agent.sample\_rate=\${SW\_AGENT\_SAMPLE:10000}

\# 4. 日志输出(可选,开启后便于排查Agent问题)

logging.level=\${SW\_LOGGING\_LEVEL:INFO}

logging.file\_name=\${SW\_LOGGING\_FILE\_NAME:skywalking-agent.log}
3.2.3 启动服务时挂载 Agent

通过 JVM 参数-javaagent挂载 Agent,以 Spring Boot 服务为例:

  1. 本地开发环境 (IDEA):在Run/Debug Configurations中添加 VM 参数:
shell 复制代码
-javaagent:D:/skywalking-agent/skywalking-agent.jar

-DSW\_AGENT\_NAME=order-service

-DSW\_AGENT\_COLLECTOR\_BACKEND\_SERVICES=192.168.1.100:11800
  1. 生产环境(Jar 包启动):在启动脚本中添加参数:
shell 复制代码
nohup java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \\

-DSW\_AGENT\_NAME=order-service \\

-DSW\_AGENT\_COLLECTOR\_BACKEND\_SERVICES=192.168.1.100:11800 \\

-jar order-service-1.0.0.jar > order-service.log 2>&1 &
3.2.4 验证链路追踪

启动所有 Java 服务后,访问几次业务接口(如创建订单、查询商品),然后打开 SkyWalking UI(http://服务器IP:8080):

  • 在 "服务列表" 中能看到所有挂载 Agent 的服务(user-service、order-service 等);

  • 在 "链路追踪" 中可查看具体接口的调用链路,包括各服务的调用顺序、耗时、是否有异常。

四、实战第三步:Grafana 可视化配置(指标 + 链路)

4.1 添加数据源

Grafana 需分别对接 Prometheus(指标)和 SkyWalking(链路),步骤如下:

4.1.1 添加 Prometheus 数据源
  1. 登录 Grafana,点击左侧菜单 "Configuration> Data Sources",点击 "Add data source";

  2. 搜索 "Prometheus",选择后配置:

  • Name:Prometheus(自定义名称);

  • URL:http://prometheus:9090(Docker 内部网络,直接使用容器名访问);

  • 其他保持默认,点击 "Save & test",显示 "Data source is working" 即为成功。

4.1.2 添加 SkyWalking 数据源
  1. 点击 "Add data source",搜索 "SkyWalking"(若未找到,需先在 Grafana 插件市场安装 SkyWalking 插件);

  2. 配置:

  • Name:SkyWalking;

  • URL:http://skywalking-oap:12800(OAP Server 的 HTTP 接口地址);

  • 其他保持默认,点击 "Save & test",显示 "Success" 即为成功。

4.2 配置监控面板

Grafana 面板支持 "导入模板" 和 "自定义创建",推荐先导入成熟模板快速实现基础监控,再根据业务需求自定义。

4.2.1 导入 Spring Boot 指标模板
  1. 点击左侧菜单 "Dashboards> Browse",点击 "Import";

  2. 输入 Spring Boot 指标模板 ID:12900(Grafana 官方模板,涵盖 JVM、HTTP、业务指标),点击 "Load";

  3. 选择数据源为 "Prometheus",点击 "Import",即可看到完整的 Spring Boot 服务监控面板,包含:

  • JVM 监控:堆内存、非堆内存、GC 次数、GC 耗时;

  • 接口监控:请求量、响应时间(P50/P90/P99)、错误率;

  • 系统监控:CPU 使用率、内存使用率、磁盘 IO。

4.2.2 自定义业务指标面板(以订单量监控为例)
  1. 在现有面板中点击 "Add panel",选择 "Time series"(时序图);

  2. 在 "Query" 中配置 Prometheus 查询语句:

  • 指标:order_create_total{application="order-service"}(订单创建总量);

  • 聚合方式:选择 "Rate"(按时间速率统计,单位:个 / 分钟);

  • 标签筛选:可按order_type(订单类型)或status(状态)拆分曲线;

  1. 配置面板样式:
  • Title:订单创建量(分钟级);

  • Y 轴:设置单位为 "个";

  • 曲线颜色:为不同订单类型设置不同颜色;

  1. 点击 "Apply",完成自定义面板添加。
4.2.3 整合 SkyWalking 链路数据
  1. 添加新面板,选择 "Table"(表格)或 "Graph"(图表);

  2. 在 "Query" 中选择数据源为 "SkyWalking",配置查询条件:

  • Service:选择 "order-service";

  • Endpoint:选择 "/order/create"(订单创建接口);

  • Metric:选择 "Response Time (P95)"(P95 响应时间);

  1. 配置时间范围(如最近 1 小时),即可在 Grafana 中直接查看 SkyWalking 采集的链路性能数据。

4.3 配置告警通知(以钉钉为例)

Grafana 支持对接多种告警渠道,此处以钉钉为例配置:

  1. 在钉钉群中添加 "自定义机器人",获取 WebHook 地址(如https://oapi.dingtalk.com/robot/send?access_token=xxx);

  2. 登录 Grafana,点击左侧菜单 "Alerting> Contact points",点击 "Add contact point";

  3. 配置:

  • Name:DingTalk;

  • Type:选择 "DingDing";

  • URL:填写钉钉机器人 WebHook 地址;

  • Message:自定义告警模板,示例:

shell 复制代码
【Grafana告警】

告警规则:{{ alert.name }}

告警级别:{{ alert.labels.severity }}

触发时间:{{ alert.startsAt }}

服务名称:{{ alert.labels.application }}

详情:{{ alert.annotations.description }}
  1. 点击 "Test" 发送测试告警,确认钉钉群能收到消息;

  2. 为监控指标配置告警规则:

  • 进入订单创建量面板,点击 "Alert> Create alert rule";

  • 配置触发条件:当订单创建量连续 5 分钟低于 10 个(业务低峰告警);

  • 选择通知渠道为 "DingTalk";

  • 设置告警恢复通知:勾选 "Send recovery notifications"。

相关推荐
没事学AI3 小时前
Caffeine三种缓存过期策略总结:原理、实战与调优
java·缓存·caffeine·缓存穿透防护·caffeine缓存
Micro麦可乐3 小时前
为什么两个看似相等的 Integer 却不相等?一次诡异的缓存折扣商品 BUG 排查
java·缓存·bug·包装类判断·integer判断
杨杨杨大侠3 小时前
手把手教你写 httpclient 框架(七)- 异步处理与性能优化
java·http·github
ajassi20003 小时前
开源 java android app 开发(十四)自定义绘图控件--波形图
android·java·开源
小一鹿呀3 小时前
Docker一键部署prometheus并实现飞书告警详解
docker·飞书·prometheus
一叶飘零_sweeeet3 小时前
从 0 到 1 精通 SkyWalking:分布式系统的 “透视镜“ 技术全解析
java·skywalking
七夜zippoe3 小时前
Java 生态监控体系实战:Prometheus+Grafana+SkyWalking 整合全指南(三)
java·grafana·prometheus
陈遇巧4 小时前
Spring Framework
java·笔记·spring
我是华为OD~HR~栗栗呀4 小时前
20届-高级开发(华为oD)-Java面经
java·c++·后端·python·华为od·华为