Grafana 监控服务指标使用指南:打造可视化监控体系

前言

在现代应用开发中,监控系统已经成为保障服务稳定性和可靠性的关键组成部分。通过实时监控应用的各项指标,我们可以及时发现潜在问题,快速定位故障原因,甚至预测系统可能出现的风险。

Grafana 作为一款功能强大的开源可视化监控工具,结合 Prometheus 等时序数据库,可以帮助我们构建一套完整的监控体系。本文将详细介绍如何使用 Grafana 监控 Spring Boot 应用的服务指标,从依赖引入到面板配置,全方位覆盖监控系统的搭建和使用。

1. 监控体系架构

在开始实际操作之前,让我们先了解一下本文将要搭建的监控体系架构:

  1. 应用层:Spring Boot 应用,通过 Actuator 和 Micrometer 暴露指标
  2. 采集层:Prometheus,负责采集和存储应用指标
  3. 可视化层:Grafana,负责将指标数据可视化展示

这种架构是目前业界比较流行的监控方案,具有以下优势:

  • 低侵入性:通过依赖引入即可实现基础监控
  • 可扩展性:支持自定义业务指标
  • 可视化效果好:Grafana 提供丰富的图表类型和配置选项
  • 告警能力强:支持设置告警规则,及时发现问题

2. 依赖引入

在项目的 pom.xml 文件中添加以下依赖:

xml 复制代码
<!-- 监控核心 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <!-- 使用与项目 Spring Boot 版本匹配的版本 -->
</dependency>

<!-- Prometheus 指标 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <!-- 使用与项目 Spring Boot 版本匹配的版本 -->
</dependency>

依赖说明

  • spring-boot-starter-actuator:Spring Boot 提供的监控核心依赖,暴露各种监控端点
  • micrometer-registry-prometheus:Micrometer 的 Prometheus 注册表实现,用于将应用指标转换为 Prometheus 格式

3. 配置

在项目的 application.ymlapplication.properties 文件中添加以下配置:

3.1 基本配置

yaml 复制代码
management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus  # 暴露的端点
  endpoint:
    health:
      show-details: always  # 显示健康检查的详细信息

3.2 高级配置(可选)

yaml 复制代码
management:
  metrics:
    tags:
      application: ${spring.application.name}  # 添加应用名称标签
    export:
      prometheus:
        enabled: true
        step: 1m  # 指标收集间隔

配置说明

  • management.endpoints.web.exposure.include:指定需要暴露的端点,这里我们暴露了 healthinfoprometheus 三个端点
  • management.endpoint.health.show-details:设置为 always 可以在健康检查端点中显示详细信息
  • management.metrics.tags:为所有指标添加全局标签,这里添加了应用名称标签,便于在多应用场景下区分
  • management.metrics.export.prometheus.step:设置指标导出的时间间隔,默认为 1 分钟

4. Prometheus 和 Grafana 部署

4.1 使用 Docker 部署

4.1.1 创建 docker-compose.yml 文件
yaml 复制代码
version: '3'
services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    restart: always

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    volumes:
      - grafana-storage:/var/lib/grafana
    restart: always
    depends_on:
      - prometheus

volumes:
  grafana-storage:
4.1.2 创建 prometheus.yml 配置文件
yaml 复制代码
global:
  scrape_interval: 15s  # 全局抓取间隔

scrape_configs:
  - job_name: 'spring-application'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['host.docker.internal:8080']  # 应用服务地址,Windows 环境使用 host.docker.internal
        # 如果是 Linux 环境,使用实际的 IP 地址,例如:['192.168.1.100:8080']

配置说明

  • scrape_interval:设置 Prometheus 的全局抓取间隔,默认为 15 秒
  • job_name:设置抓取任务的名称,便于在 Prometheus 中识别
  • metrics_path:指定指标暴露的路径,Spring Boot 应用默认是 /actuator/prometheus
  • targets:指定需要抓取的目标地址,这里需要根据实际环境设置
4.1.3 启动服务

在包含 docker-compose.yml 文件的目录中执行:

bash 复制代码
docker-compose up -d

4.2 访问地址

5. 自定义指标添加(Micrometer 业务指标常见编码案例)

5.1 注入 MeterRegistry

java 复制代码
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MetricsService {

    private final MeterRegistry registry;

    @Autowired
    public MetricsService(MeterRegistry registry) {
        this.registry = registry;
    }

    // 指标相关方法
}

5.2 计数器(Counter)

用于统计事件发生的次数,例如成功请求数、失败请求数等。

5.2.1 编程式开发
java 复制代码
// 基本计数器
Counter successCounter = Counter.builder("success_total")
    .description("成功次数")
    .tag("service", "user")  // 添加标签
    .register(registry);

// 使用计数器
successCounter.increment();  // 增加 1
successCounter.increment(5);  // 增加指定值
5.2.2 注解式开发

从 Spring Boot 2.5+ 开始,可以直接使用 Micrometer 提供的 @io.micrometer.core.annotation.Counted 注解来实现计数器功能:

使用示例

java 复制代码
import io.micrometer.core.annotation.Counted;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    // 使用 Micrometer 提供的 @Counted 注解
    @Counted(value = "user.login.count", 
             description = "用户登录次数",
             extraTags = {"service", "user", "operation", "login"})
    @GetMapping("/api/user/login")
    public String login(String username, String password) {
        // 执行业务逻辑
        return "登录成功";
    }
}

注解参数说明

  • value:计数器名称,默认值为被注解方法的完全限定名
  • description:计数器描述
  • extraTags:额外的标签,格式为 {"key1", "value1", "key2", "value2"}
  • recordFailuresOnly:是否只记录失败的调用,默认为 false
  • failureTag:当 recordFailuresOnlytrue 时,失败标签的名称

注意事项

  • 要使 @Counted 注解生效,需要确保应用中已配置 MeterRegistry 实例
  • 对于 Spring Boot 应用,只要添加了相关依赖,Spring Boot 会自动配置 MeterRegistry
  • 注解式计数器会在方法执行完成后自动增加计数,无需手动调用 increment() 方法

5.3 仪表盘(Gauge)

用于测量当前值,例如当前在线用户数、队列长度等。

java 复制代码
// 基本仪表盘
AtomicInteger onlineUsers = new AtomicInteger(0);
Gauge.builder("online_users", onlineUsers, AtomicInteger::get)
    .description("当前在线用户数")
    .register(registry);

// 使用仪表盘
onlineUsers.incrementAndGet();  // 增加在线用户数
onlineUsers.decrementAndGet();  // 减少在线用户数

5.4 计时器(Timer)

用于测量操作的执行时间,例如请求处理时间、方法执行时间等。

5.4.1 编程式开发
java 复制代码
// 方法 1:手动计时
Timer timer = Timer.builder("request_processing_time")
    .description("请求处理时间")
    .tag("endpoint", "/api/user")
    .register(registry);

// 使用计时器
Timer.Sample sample = Timer.start(registry);
try {
    // 执行业务逻辑
    Thread.sleep(100);
} catch (InterruptedException e) {
    e.printStackTrace();
} finally {
    sample.stop(timer);
}
5.4.2 注解式开发

从 Spring Boot 2.5+ 开始,可以直接使用 Micrometer 提供的 @Timed 注解来实现方法执行时间的监控,无需手动创建计时器实例。

依赖要求

  • Spring Boot 2.5+
  • 确保已添加 spring-boot-starter-actuatormicrometer-registry-prometheus 依赖

使用示例

java 复制代码
import io.micrometer.core.annotation.Timed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    // 使用 Micrometer 提供的 @Timed 注解
    @Timed(
        value = "user.get",             // 计时器名称
        description = "获取用户信息的时间",  // 计时器描述
        extraTags = {"endpoint", "/api/user/{id}"},  // 额外标签
        longTask = false,                // 是否为长任务
        percentiles = {0.5, 0.9, 0.99}   // 需要统计的百分位数
    )
    @GetMapping("/api/user/{id}")
    public User getUserById(@PathVariable Long id) {
        // 执行业务逻辑
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new User(id, "张三");
    }
}

注解参数说明

  • value:计时器名称,默认值为被注解方法的完全限定名
  • description:计时器描述
  • extraTags:额外的标签,格式为 {"key1", "value1", "key2", "value2"}
  • longTask:是否为长任务,默认为 false
  • percentiles:需要统计的百分位数,例如 {0.5, 0.9, 0.99} 表示统计 50%、90% 和 99% 百分位数
  • histogram:是否启用直方图,默认为 false
  • recordFailuresOnly:是否只记录失败的调用,默认为 false

使用注意事项

  • 要使 @Timed 注解生效,需要确保应用中已配置 MeterRegistry 实例
  • 对于 Spring Boot 应用,只要添加了相关依赖,Spring Boot 会自动配置 MeterRegistry
  • 注解式计时器会在方法执行完成后自动记录执行时间,无需手动调用计时方法
  • 可以通过 extraTags 参数添加业务相关的标签,便于在 Grafana 中进行多维度分析

5.5 分布摘要(DistributionSummary)

用于测量事件的分布情况,例如响应大小、订单金额等。

java 复制代码
// 基本分布摘要
DistributionSummary responseSize = DistributionSummary.builder("response_size")
    .description("响应大小")
    .baseUnit("bytes")
    .register(registry);

// 使用分布摘要
responseSize.record(1024);  // 记录 1024 bytes

6. Grafana 监控面板配置

6.1 添加 Prometheus 数据源

  1. 登录 Grafana(默认地址:http://localhost:3000,默认用户名/密码:admin/admin)
  2. 点击左侧菜单的 "Configuration" -> "Data sources"
  3. 点击 "Add data source"
  4. 选择 "Prometheus"
  5. 在 "URL" 字段中输入 Prometheus 的地址(例如:http://prometheus:9090
  6. 点击 "Save & Test" 按钮,确保连接成功

6.2 创建监控面板

  1. 点击左侧菜单的 "Create" -> "Dashboard"
  2. 点击 "Add new panel"
  3. 在 "Query" 标签页中,选择之前添加的 Prometheus 数据源
  4. 在查询编辑器中输入 PromQL 查询语句,例如:
    • 查看成功次数:success_total{service="user"}
    • 查看在线用户数:online_users
    • 查看请求处理时间:rate(request_processing_time_sum[5m]) / rate(request_processing_time_count[5m])
  5. 在 "Visualization" 标签页中选择合适的图表类型(例如:Graph、Gauge、Stat 等)
  6. 在 "General" 标签页中设置面板标题和描述
  7. 点击 "Apply" 按钮保存面板
  8. 点击 "Save dashboard" 按钮保存整个仪表盘

6.3 导入预定义仪表盘

Grafana 提供了许多预定义的仪表盘模板,可以直接导入使用:

  1. 点击左侧菜单的 "Create" -> "Import"
  2. 输入仪表盘 ID(例如:12856 是 Spring Boot 2.1 监控仪表盘)
  3. 选择之前添加的 Prometheus 数据源
  4. 点击 "Import" 按钮导入仪表盘

6.4 实用监控面板推荐

  1. 系统概览面板:显示 CPU、内存、磁盘等系统指标
  2. 应用性能面板:显示请求量、响应时间、错误率等应用指标
  3. 业务指标面板:显示与业务相关的指标,例如订单量、用户活跃度等
  4. JVM 监控面板:显示 JVM 相关指标,例如堆内存使用情况、GC 次数等

7. 告警配置

Grafana 不仅可以展示指标,还可以设置告警规则,当指标达到阈值时发送通知。

7.1 创建告警规则

  1. 打开需要设置告警的面板
  2. 点击面板标题,选择 "Edit"
  3. 切换到 "Alert" 标签页
  4. 点击 "Create Alert"
  5. 设置告警规则,包括:
    • 告警名称
    • 评估时间窗口
    • 条件表达式
    • 阈值
    • 通知方式
  6. 点击 "Save" 按钮保存告警规则

7.2 配置通知渠道

  1. 点击左侧菜单的 "Alerting" -> "Notification channels"
  2. 点击 "Add channel"
  3. 选择通知类型(例如:Email、Slack、Webhook 等)
  4. 填写通知配置
  5. 点击 "Save" 按钮保存通知渠道

8. 常见问题和解决方案

8.1 无法访问 /actuator/prometheus 端点

问题 :访问 http://localhost:8080/actuator/prometheus 时返回 404 错误。

解决方案

  • 检查依赖是否正确引入
  • 检查配置文件中的 management.endpoints.web.exposure.include 是否包含 prometheus
  • 检查应用是否正常启动

8.2 Prometheus 无法抓取指标

问题:在 Prometheus 中查看目标状态时显示 "DOWN"。

解决方案

  • 检查 prometheus.yml 中的 targets 配置是否正确
  • 检查应用是否可以正常访问 /actuator/prometheus 端点
  • 检查网络连接是否正常

8.3 Grafana 中没有数据

问题:在 Grafana 面板中看不到数据。

解决方案

  • 检查数据源配置是否正确
  • 检查查询语句是否正确
  • 检查 Prometheus 是否成功抓取到指标
  • 检查时间范围是否设置正确

8.4 指标值不准确

问题:监控面板中的指标值与实际情况不符。

解决方案

  • 检查指标的定义和使用是否正确
  • 检查标签的使用是否合理
  • 检查查询语句是否正确理解了指标的含义

9. 最佳实践

9.1 指标设计原则

  1. 命名规范 :指标名称应使用 snake_case 格式,例如 http_requests_total
  2. 标签合理:使用有意义的标签,便于多维度分析,但标签数量不宜过多
  3. 粒度适当:根据监控需求设计合适粒度的指标,避免指标过多或过少
  4. 类型匹配:根据监控对象选择合适的指标类型(Counter、Gauge、Timer 等)

9.2 监控体系建设建议

  1. 分层监控:建立应用层、中间件层、系统层的分层监控体系
  2. 告警策略:设置合理的告警阈值和通知策略,避免告警风暴
  3. 面板标准化:为不同类型的应用创建标准化的监控面板
  4. 定期review:定期 review 监控指标和面板,确保监控的有效性
  5. 持续优化:根据实际使用情况,持续优化监控体系

9.3 性能优化

  1. 减少指标数量:只监控必要的指标,避免过多指标影响系统性能
  2. 合理设置抓取间隔:根据指标变化频率设置合适的抓取间隔
  3. 使用标签选择器:在查询时使用标签选择器,减少数据传输量
  4. 启用压缩:启用 Prometheus 和 Grafana 之间的通信压缩

10. 总结

通过本文的介绍,我们已经学习了如何使用 Grafana 监控 Spring Boot 应用的服务指标,从依赖引入到面板配置,构建了一套完整的监控体系。

监控系统的建设是一个持续的过程,需要根据应用的实际情况不断调整和优化。合理的监控体系不仅可以帮助我们及时发现和解决问题,还可以为系统的性能优化和容量规划提供数据支持。

相关推荐
€8112 小时前
Java入门级教程26——序列化和反序列化,Redis存储Java对象、查询数据库与实现多消费者消息队列
java·拦截器·序列化和反序列化·数据库查询·redis存储java对象·多消费者消息队列
多多*2 小时前
Mysql数据库相关 事务 MVCC与锁的爱恨情仇 锁的层次架构 InnoDB锁分析
java·数据库·windows·sql·oracle·面试·哈希算法
gAlAxy...2 小时前
SpringBoot Servlet 容器全解析:嵌入式配置与外置容器部署
spring boot·后端·servlet
cyforkk2 小时前
15、Java 基础硬核复习:File类与IO流的核心逻辑与面试考点
java·开发语言·面试
李少兄2 小时前
解决 org.springframework.context.annotation.ConflictingBeanDefinitionException 报错
java·spring boot·mybatis
大飞哥~BigFei2 小时前
整数ID与短字符串互转思路及开源实现分享
java·开源
benjiangliu2 小时前
LINUX系统-09-程序地址空间
android·java·linux
历程里程碑2 小时前
子串-----和为 K 的子数组
java·数据结构·c++·python·算法·leetcode·tornado
BYSJMG3 小时前
计算机毕业设计选题推荐:基于Hadoop的城市交通数据可视化系统
大数据·vue.js·hadoop·分布式·后端·信息可视化·课程设计