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 应用的服务指标,从依赖引入到面板配置,构建了一套完整的监控体系。

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

相关推荐
devlei6 分钟前
从源码泄露看AI Agent未来:深度对比Claude Code原生实现与OpenClaw开源方案
android·前端·后端
pshdhx_albert39 分钟前
AI agent实现打字机效果
java·http·ai编程
沉鱼.441 小时前
第十二届题目
java·前端·算法
努力的小郑2 小时前
Canal 不难,难的是用好:从接入到治理
后端·mysql·性能优化
赫瑞2 小时前
数据结构中的排列组合 —— Java实现
java·开发语言·数据结构
Victor3562 小时前
MongoDB(87)如何使用GridFS?
后端
Victor3562 小时前
MongoDB(88)如何进行数据迁移?
后端
小红的布丁3 小时前
单线程 Redis 的高性能之道
redis·后端
GetcharZp3 小时前
Go 语言只能写后端?这款 2D 游戏引擎刷新你的认知!
后端
周末也要写八哥3 小时前
多进程和多线程的特点和区别
java·开发语言·jvm