一、为什么需要监控Spring Boot应用

开发一个应用就像养一盆植物,光写好代码种下去还不够,得随时看看它是否健康。比如:

  • 请求处理时间是否变长了?
  • 内存是不是悄悄泄漏了?
  • 某个接口突然没人访问了,是不是出问题了?

这时候就需要监控指标来当我们的"植物健康检测仪"。Spring Boot自带了一套简单的监控机制(比如/actuator端点),但想要更专业的分析,还得自己动手采集数据。

技术栈:Spring Boot + Micrometer + Prometheus

// 示例1:快速启用Spring Boot基础监控
@SpringBootApplication
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
    }
}

// 在application.properties中添加:
// management.endpoints.web.exposure.include=health,info,metrics 
// management.endpoint.health.show-details=always

二、指标采集的四种实用方法

方法1:使用Micrometer暴露指标

Micrometer是Spring Boot的"指标翻译官",能把JVM内存、线程池等信息转换成Prometheus能读懂的格式。

// 示例2:自定义业务指标统计
@Service
public class OrderService {
    // 定义一个计数器统计下单次数
    private final Counter orderCounter = Metrics.counter("order.count");

    public void createOrder() {
        orderCounter.increment();
        // 业务逻辑...
    }
}

方法2:手动埋点复杂逻辑

当自动采集不够用时,可以像插旗帜一样在关键位置埋点:

// 示例3:记录方法执行时间
@Timed("user.query.time")  // 这个注解会自动生成时间指标
public List<User> queryUsers() {
    return userRepository.findAll();
}

方法3:对接Prometheus存储

采集到的数据需要有个仓库存储,Prometheus就像个超大号Excel:

# 示例4:Prometheus配置片段
scrape_configs:
  - job_name: 'spring'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['localhost:8080']

方法4:Grafana可视化

数据变成图表才好看,Grafana的仪表盘就像汽车仪表盘:

-- 示例5:Grafana面板常用PromQL查询
http_server_requests_seconds_count{uri="/api/users"}  -- 统计接口调用次数
jvm_memory_used_bytes{area="heap"}                     -- 堆内存使用量

三、性能分析的五个经典场景

场景1:发现慢接口

假设发现/api/report接口很慢,我们可以:

  1. 先看该接口的耗时百分位数值
  2. 对比数据库查询次数
  3. 检查是否持有锁时间过长
// 示例6:模拟慢接口诊断
@GetMapping("/api/report")
public Report generateReport() {
    Timer.Sample sample = Timer.start(); // 开始计时
    
    // 1. 查数据库
    List<Data> data = dataService.fetchHugeData(); 
    
    // 2. 复杂计算
    HeavyCalculator.calculate(data);
    
    // 3. 记录总耗时
    sample.stop(Metrics.timer("report.generate.time"));
    return new Report(data);
}

场景2:内存泄漏排查

内存使用曲线持续上涨时:

  1. /actuator/heapdump获取内存快照
  2. 用MAT工具分析哪些对象占着内存不放
  3. 检查是否有静态集合不断增长
// 示例7:疑似内存泄漏代码
public class CacheManager {
    private static Map<String, Object> BIG_CACHE = new HashMap<>();
    
    public void addToCache(String key, Object value) {
        BIG_CACHE.put(key, value); // 危险!静态Map会一直增长
    }
}

四、落地实践的注意事项

  1. 采样频率:生产环境建议15秒采集一次,太频繁会影响性能
  2. 指标命名:遵循aaa.bbb.ccc的层级约定,比如http.requests.duration
  3. 报警阈值
    • CPU使用率超70%持续5分钟
    • 错误率超过1%立即报警
  4. 存储周期:原始数据保留15天,聚合数据保留1年
// 示例8:合理的指标命名规范
// 好的命名 👇
Metrics.counter("api.login.attempts", "type", "sms");
// 坏的命名 ❌
Metrics.counter("countLoginSms");

五、技术方案对比

方案 优点 缺点
Spring Boot Actuator 开箱即用 功能简单
Prometheus 查询强大 需要额外部署
ELK 日志关联分析 资源消耗大

六、总结

监控系统就像给应用安装行车记录仪,既要记录常规指标(车速、油耗),也要能紧急抓拍异常瞬间(急刹车)。好的监控应该:

  1. 用最少资源采集关键数据
  2. 能快速定位问题根因
  3. 提供历史对比参考

下次当老板问"系统为什么又挂了"时,你就能指着监控图说:"看,是数据库连接池在凌晨3点耗尽了!"