1. 为什么需要SpringBoot应用监控系统?
在分布式系统架构中,服务实例数量可能达到数百甚至上千个。我曾遇到一个线上事故:某核心服务在凌晨3点CPU使用率飙升到90%,但由于缺乏有效监控,直到早上用户投诉才发现问题。这种被动响应模式在微服务时代已经完全不可行。
SpringBoot作为Java生态中最主流的微服务框架,其应用健康状态、性能指标和业务数据的实时监控已成为刚需。传统方案如Zabbix对Java应用的指标采集粒度不够细,而Prometheus+Grafana的组合恰好解决了三个核心痛点:
- 多维数据模型:支持按服务名、实例IP、接口路径等多维度聚合指标
- 强大的查询语言PromQL:可以计算接口99线响应时间这类复杂指标
- 可视化与告警一体化:从数据采集到图形展示再到触发告警的全流程闭环
2. 监控系统架构设计
2.1 组件选型与协作流程
这套监控系统的核心组件工作流程如下(->表示数据流向):
code复制SpringBoot应用 --指标暴露--> Prometheus --拉取存储--> Grafana --可视化--> 告警通知
关键组件选型考量:
-
Prometheus vs InfluxDB:
- 优势:原生支持服务发现、更适合动态变化的微服务环境
- 劣势:不支持集群部署(需通过Thanos等方案扩展)
-
Grafana vs Kibana:
- 优势:更丰富的数据源支持、更灵活的仪表盘配置
- 劣势:日志分析能力较弱(需配合Loki使用)
2.2 监控指标体系规划
根据多年经验,建议监控这些核心指标:
| 指标类型 | 具体指标示例 | 采集频率 | 告警阈值 |
|---|---|---|---|
| JVM监控 | 堆内存使用率、GC次数 | 15s | >80%持续5分钟 |
| 接口性能 | 99线响应时间、QPS | 30s | >500ms或<10rps |
| 系统资源 | CPU负载、磁盘IO | 60s | >70%持续10分钟 |
| 自定义业务指标 | 订单创建失败率、支付超时次数 | 自定义 | 根据业务场景设定 |
3. SpringBoot集成Prometheus
3.1 依赖配置实操
在pom.xml中添加这些关键依赖:
xml复制<!-- 基础监控支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Prometheus格式输出 -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.9.3</version>
</dependency>
application.yml需要特别配置的端点:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,prometheus # 只暴露必要端点
metrics:
tags:
application: ${spring.application.name} # 添加应用标签
3.2 自定义指标开发
比如要监控订单服务异常次数:
java复制@RestController
public class OrderController {
private final Counter orderFailCounter;
public OrderController(MeterRegistry registry) {
this.orderFailCounter = Counter.builder("order.fail.count")
.description("订单创建失败次数")
.tag("module", "order")
.register(registry);
}
@PostMapping("/order")
public String createOrder() {
try {
// 业务逻辑
return "success";
} catch (Exception e) {
orderFailCounter.increment(); // 失败时计数
throw e;
}
}
}
重要提示:在高并发场景下,直接使用Counter可能导致性能问题。建议使用MetricsBuffer进行批量上报。
4. Prometheus服务部署
4.1 安装与配置详解
使用Docker部署时,prometheus.yml关键配置:
yaml复制scrape_configs:
- job_name: 'springboot-apps'
metrics_path: '/actuator/prometheus'
scrape_interval: 15s
static_configs:
- targets: ['host.docker.internal:8080'] # 本地开发环境
relabel_configs:
- source_labels: [__address__]
target_label: instance
- source_labels: [__meta_service_name]
target_label: service
对于K8S环境,建议使用ServiceMonitor:
yaml复制apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: springboot-monitor
spec:
selector:
matchLabels:
app: my-springboot-app
endpoints:
- port: web
path: /actuator/prometheus
interval: 30s
4.2 存储优化方案
Prometheus的本地存储经常会遇到磁盘空间问题,这里分享几个实战技巧:
- 数据保留策略:
yaml复制# prometheus.yml中配置
storage:
tsdb:
retention: 15d # 根据磁盘容量调整
- 使用远程存储:
bash复制# 启动时添加参数
--storage.tsdb.retention.time=30d \
--storage.remote.write-url=http://thanos-receive:10908/api/v1/receive
- 定期清理旧数据:
bash复制# 找出过期的block并删除
find /prometheus/data -name '01*' -mtime +30 -exec rm -rf {} \;
5. Grafana可视化实战
5.1 仪表盘配置技巧
创建JVM监控面板时,这些PromQL非常实用:
- 堆内存使用率:
code复制sum(jvm_memory_used_bytes{area="heap"}) by (instance) /
sum(jvm_memory_max_bytes{area="heap"}) by (instance) * 100
- GC暂停时间(最近5分钟):
code复制rate(jvm_gc_pause_seconds_sum[5m]) / rate(jvm_gc_pause_seconds_count[5m])
- 接口99线响应时间:
code复制histogram_quantile(0.99,
sum(rate(http_server_requests_seconds_bucket[1m])) by (le, uri))
专业建议:为关键指标设置Overrides,当值超过阈值时自动变色。比如当CPU>80%时显示为红色。
5.2 告警规则配置
在Grafana中配置邮件告警的完整流程:
- 首先配置SMTP:
ini复制[smtp]
enabled = true
host = smtp.exmail.qq.com:465
user = alert@yourcompany.com
password = xxx
from_address = alert@yourcompany.com
- 创建告警规则示例:
sql复制# 当订单失败率持续5分钟>1%时触发
sum(rate(order_fail_count[5m])) by (service) /
sum(rate(order_total_count[5m])) by (service) > 0.01
- 告警消息模板优化:
code复制{{ define "alert.message" }}
[{{ .Status | toUpper }}] {{ .Labels.alertname }}
应用: {{ .Labels.service }}
实例: {{ .Labels.instance }}
当前值: {{ .Value }}
触发时间: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
6. 生产环境调优经验
6.1 性能优化方案
在高负载场景下,我们遇到过Prometheus内存溢出问题。这些参数调整很有效:
yaml复制# prometheus启动参数优化
--storage.tsdb.retention.time=7d \
--query.max-concurrency=20 \
--query.timeout=2m \
--storage.tsdb.memory-chunks=5000000
对于SpringBoot应用,建议调整指标采集:
yaml复制management:
metrics:
export:
prometheus:
step: 1m # 降低采集频率
enable:
jvm: true
system: true
http: true
logback: false # 关闭不必要指标
6.2 常见故障排查
-
Prometheus抓取失败:
- 检查网络连通性:
telnet <app-ip> 8080 - 验证端点可访问:
curl http://localhost:8080/actuator/prometheus - 查看Prometheus日志:
journalctl -u prometheus -f
- 检查网络连通性:
-
Grafana显示无数据:
- 检查数据源配置:确保URL为
http://prometheus:9090 - 验证时间范围:避免选择了未来时间
- 查看PromQL语法:在Prometheus自带的Graph页面先测试
- 检查数据源配置:确保URL为
-
告警不触发:
- 检查Evaluation Interval是否设置过小
- 验证For Duration是否足够长(避免抖动)
- 测试Contact Point:手动发送测试消息
7. 进阶扩展方案
7.1 多集群监控
通过Thanos实现全局视图:
yaml复制# thanos-sidecar配置示例
- --prometheus.url=http://localhost:9090
- --tsdb.path=/prometheus
- --objstore.config-file=/etc/thanos/bucket.yml
7.2 自定义Exporter开发
当需要监控DB2等特殊系统时,可以开发自定义Exporter:
go复制func main() {
db2Exporter := exporter.NewDB2Exporter()
prometheus.MustRegister(db2Exporter)
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(":9111", nil))
}
7.3 监控数据持久化
将数据长期存储到InfluxDB的方案:
yaml复制remote_write:
- url: http://influxdb:8086/api/v1/prom/write?db=prometheus
queue_config:
max_samples_per_send: 10000
capacity: 20000
在Grafana中配置InfluxDB数据源时,建议使用Flux查询语言:
flux复制from(bucket: "prometheus")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "jvm_memory_used_bytes")
这套监控系统在我们生产环境稳定运行3年,日均处理20亿指标数据。最关键的经验是:监控指标在精不在多,建议每个服务重点关注5-10个核心指标,配合智能基线告警(如同比上周同一时间增长50%),才能真正发挥监控系统的价值。
