在开发Java应用时,我们经常会遇到这样的场景:线上服务突然变慢,用户投诉不断,但开发团队却找不到具体原因。这时候如果有完善的性能监控体系,就能快速定位是JVM内存泄漏、数据库连接池耗尽,还是某个API接口响应时间异常。这就是为什么我们需要构建基于Prometheus+Grafana的监控体系。
我经历过一个真实案例:一个日活百万的Spring Boot应用,在促销活动时频繁出现502错误。当时没有完善的监控,团队花了3天才发现是线程池配置不合理导致请求堆积。如果提前部署了这套监控方案,问题可能在30分钟内就能解决。
性能监控体系的核心价值在于:
推荐使用Docker部署整套监控系统,既方便又干净。这是我验证过的兼容性最好的版本组合:
bash复制# 检查Docker环境
docker --version # 要求20.10+
docker-compose --version # 要求1.29+
如果还没安装Docker,可以用这个一键脚本(适用于CentOS/Ubuntu):
bash复制curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
Prometheus的Docker镜像有很多选择,我推荐使用官方的prom/prometheus:
bash复制# 创建配置目录
mkdir -p /opt/prometheus/{data,conf}
# 下载示例配置文件
wget https://raw.githubusercontent.com/prometheus/prometheus/main/documentation/examples/prometheus.yml -O /opt/prometheus/conf/prometheus.yml
# 启动容器
docker run -d \
--name=prometheus \
-p 9090:9090 \
-v /opt/prometheus/conf:/etc/prometheus \
-v /opt/prometheus/data:/prometheus \
prom/prometheus \
--config.file=/etc/prometheus/prometheus.yml
这里有个坑要注意:如果直接使用默认配置,Prometheus会频繁采集自身指标,可能导致资源浪费。建议修改配置文件的scrape_interval为30s:
yaml复制global:
scrape_interval: 30s
evaluation_interval: 30s
Grafana的安装更简单,但有几个优化参数很实用:
bash复制docker run -d \
--name=grafana \
-p 3000:3000 \
-v /opt/grafana/data:/var/lib/grafana \
-e "GF_SECURITY_ADMIN_PASSWORD=your_secure_password" \
-e "GF_USERS_ALLOW_SIGN_UP=false" \
grafana/grafana-enterprise
特别提醒:
Configuration -> Preferences中将时区改为Local Browser TimeEmbedded Dashboards功能方便团队协作对于Spring Boot应用,最成熟的方案是通过Micrometer接入。需要在pom.xml中添加:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.9.0</version>
</dependency>
然后在application.yml中配置:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
export:
prometheus:
enabled: true
tags:
application: ${spring.application.name} # 重要!用于区分不同服务
默认配置会暴露以下核心指标:
如果需要监控业务指标,可以使用Micrometer的Counter和Timer:
java复制@Service
public class OrderService {
private final Counter orderCounter;
private final Timer paymentTimer;
public OrderService(MeterRegistry registry) {
this.orderCounter = registry.counter("order.create.count");
this.paymentTimer = registry.timer("order.payment.time");
}
public void createOrder() {
orderCounter.increment();
paymentTimer.record(() -> {
// 支付逻辑
});
}
}
指标采样:对于高频指标,可以设置采样率避免数据爆炸
yaml复制management:
metrics:
distribution:
percentiles:
order.payment.time: 0.5,0.9,0.99
sla:
order.payment.time: 1s,3s,5s
标签过滤:敏感标签可以通过以下配置过滤
yaml复制management:
metrics:
export:
prometheus:
strip-uri-parameters: true
自定义指标:通过@Timed注解实现方法级监控
java复制@Timed(value = "user.query.time", description = "用户查询耗时")
public List<User> queryUsers() {
// 查询逻辑
}
在Grafana中添加Prometheus数据源时,有几个关键参数需要注意:
http://prometheus:9090(如果是Docker网络)Prometheus Type和Disable Metrics Lookup选项根据我的经验,一个好的监控仪表盘应该遵循以下原则:
推荐导入这些官方仪表盘模板:
导入方法:
在Grafana 8.0+版本中,告警系统做了重大升级。配置HTTP接口超时告警的示例:
promql复制sum(rate(http_server_requests_seconds_count{uri!~".*actuator.*", status!="404"}[1m])) by (uri)
/
sum(rate(http_server_requests_seconds_sum{uri!~".*actuator.*", status!="404"}[1m])) by (uri)
> 3 # 3秒阈值
变量联动:在仪表盘设置变量实现服务筛选
json复制{
"name": "service",
"type": "query",
"query": "label_values(up, application)"
}
注释功能:在重大变更时添加注释标记
bash复制curl -X POST -H "Content-Type: application/json" -d '{
"text": "发布v1.2.0",
"tags": ["deploy"]
}' http://grafana:3000/api/annotations
导出快照:故障排查时可以生成临时快照链接分享给团队
在高负载环境下,Prometheus可能需要这些优化:
存储优化:
yaml复制# prometheus.yml
storage:
tsdb:
retention: 15d # 根据磁盘容量调整
chunk_encoding: zstd
资源限制:
bash复制docker update --cpus 2 --memory 4G prometheus
分片采集:对于大规模集群,可以使用Prometheus的联邦功能
yaml复制scrape_configs:
- job_name: 'federate'
scrape_interval: 60s
honor_labels: true
metrics_path: '/federate'
params:
'match[]':
- '{__name__=~"job:.*"}'
static_configs:
- targets:
- 'shard1:9090'
- 'shard2:9090'
对于关键业务系统,建议部署Prometheus的高可用方案:
yaml复制remote_write:
- url: http://victoriametrics:8428/api/v1/write
queue_config:
capacity: 10000
max_shards: 50
基础认证:
bash复制# Prometheus
docker run -e "PROMETHEUS_WEB_ENABLE_LIFECYCLE=true" -e "PROMETHEUS_WEB_AUTHENTICATION_USERNAME=admin" -e "PROMETHEUS_WEB_AUTHENTICATION_PASSWORD=secret" ...
# Grafana
[security]
disable_initial_admin_creation = true
网络隔离:
数据加密:
bash复制docker run -v /path/to/certs:/etc/ssl/grafana -e "GF_SERVER_PROTOCOL=https" -e "GF_SERVER_CERT_FILE=/etc/ssl/grafana/cert.pem" -e "GF_SERVER_CERT_KEY=/etc/ssl/grafana/key.pem" ...
这套监控体系在我负责的多个生产环境中稳定运行了2年多,经历过618、双11等大促考验。最关键的体会是:监控系统要像写代码一样持续迭代,根据业务变化不断调整指标和告警规则。比如我们发现单纯监控平均响应时间不够,后来增加了P99和P999的监控;又比如某些业务指标需要建立基线告警而非固定阈值。