大家好,我是小悟。
一、系统监控:你的应用需要"体检医生"
想象一下:你的SpringBoot应用就像一个996的程序员,每天24小时不间断工作。某天它突然"猝死"了,而你却不知道它是何时倒下、为何倒下、倒下前有没有喊"救命"... 这就是没有监控的可怕之处!
系统监控就像是:
- 健康手环:时刻监测应用的心跳(健康状态)
- 行车记录仪:记录每一次接口调用的"交通事故"
- 私人医生:自动诊断哪里出了问题,还能开药方(告警)
- 行为分析师:分析用户的"奇怪"操作模式
二、监控大作战详细步骤
第1步:基础依赖 - 准备"体检工具箱"
xml
<!-- 监控全家桶套餐 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 健康检查加强版 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 可视化监控面板 -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.7.0</version>
</dependency>
<!-- 监控指标导出到Prometheus -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
第2步:配置监控权限 - 设置"诊室门禁"
yaml
# application.yml
spring:
application:
name: my-application # 给应用起个名字,方便认领
management:
endpoints:
web:
exposure:
include: "*" # 开放所有监控端点
exclude: env,beans # 敏感信息
endpoint:
health:
show-details: always # 健康检查显示详细信息
probes:
enabled: true # 开启K8s探针支持
prometheus:
enabled: true # 开启Prometheus指标导出
metrics:
export:
prometheus:
enabled: true
tags:
application: ${spring.application.name} # 给指标打标签
info:
env:
enabled: true # 显示环境信息
# 自定义健康检查项
info:
app:
name: "超级无敌SpringBoot应用"
version: "v2.0.0"
description: "这是一个被严密监控的应用,别想偷懒!"
developer: "监控狂魔团队"
motto: "没有监控的代码就是在裸奔"
第3步:自定义健康检查 - 编写"体检项目"
typescript
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import java.util.Random;
/**
* 数据库连接健康检查
* 相当于检查应用的"消化系统"
*/
@Component("database")
public class DatabaseHealthIndicator implements HealthIndicator {
private final Random random = new Random();
@Override
public Health health() {
boolean isHealthy = checkDatabaseConnection();
if (isHealthy) {
return Health.up()
.withDetail("message", "数据库连接正常,可以愉快地CRUD啦!")
.withDetail("responseTime", "15ms")
.withDetail("activeConnections", 25)
.build();
} else {
return Health.down()
.withDetail("message", "数据库连接失败,快去检查水管(连接)!")
.withDetail("errorCode", "DB_CONN_001")
.withDetail("suggestion", "试试重启大法?")
.build();
}
}
private boolean checkDatabaseConnection() {
// 模拟检查,真实项目应该真的ping一下数据库
return random.nextInt(100) > 10; // 90%的概率健康
}
}
/**
* 缓存健康检查
* 相当于检查应用的"短期记忆"
*/
@Component("cache")
public class CacheHealthIndicator implements HealthIndicator {
@Override
public Health health() {
return Health.up()
.withDetail("status", "缓存运行正常")
.withDetail("memoryUsage", "45%")
.withDetail("hitRate", "89.7%")
.withDetail("motto", "记不住的东西,交给缓存吧!")
.build();
}
}
/**
* 外部API依赖检查
* 相当于检查应用的"社交能力"
*/
@Component("externalApi")
public class ExternalApiHealthIndicator implements HealthIndicator {
@Override
public Health health() {
// 模拟检查第三方API
boolean wechatApi = checkWechatApi();
boolean paymentApi = checkPaymentApi();
if (wechatApi && paymentApi) {
return Health.up()
.withDetail("wechat", "微信API:连接正常,可以愉快聊天")
.withDetail("payment", "支付API:钱包鼓鼓,随时收钱")
.withDetail("overall", "所有外部API都很给力!")
.build();
} else {
return Health.down()
.withDetail("wechat", wechatApi ? "正常" : "失联中...")
.withDetail("payment", paymentApi ? "正常" : "掉线了,没法收钱!")
.withDetail("emergency", "快联系第三方客服!")
.build();
}
}
private boolean checkWechatApi() {
return true; // 假装检查
}
private boolean checkPaymentApi() {
return new Random().nextInt(100) > 5; // 95%可用率
}
}
第4步:自定义监控指标 - 安装"行为记录仪"
arduino
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 业务指标监控
* 相当于给应用安装"计步器"和"心率监测"
*/
@Component
public class BusinessMetrics {
// 用户注册计数器(统计有多少人"入坑")
private final Counter userRegistrationCounter;
// 订单创建计数器(统计赚了多少钱)
private final Counter orderCreationCounter;
// 异常计数器(统计出了多少bug)
private final Counter exceptionCounter;
// 活跃用户数(看看多少人在"玩")
private final AtomicInteger activeUsers;
// API响应时间计时器(看看接口是不是"拖延症")
private final Timer apiResponseTimer;
// 自定义业务指标(比如:点赞数、评论数等)
private final Counter likeCounter;
public BusinessMetrics(MeterRegistry registry) {
// 初始化所有指标
userRegistrationCounter = Counter.builder("user.registration.total")
.description("用户注册总数")
.tag("application", "my-app")
.register(registry);
orderCreationCounter = Counter.builder("order.created.total")
.description("订单创建总数")
.tag("application", "my-app")
.register(registry);
exceptionCounter = Counter.builder("exception.total")
.description("异常发生总数")
.tag("application", "my-app")
.register(registry);
activeUsers = registry.gauge("user.active.current",
new AtomicInteger(0));
apiResponseTimer = Timer.builder("api.response.time")
.description("API响应时间")
.publishPercentiles(0.5, 0.95, 0.99) // 统计50%, 95%, 99%分位
.register(registry);
likeCounter = Counter.builder("content.like.total")
.description("内容点赞总数")
.tag("application", "my-app")
.register(registry);
}
// 用户注册时调用(又有人"入坑"啦!)
public void incrementUserRegistration() {
userRegistrationCounter.increment();
System.out.println("恭喜!又有新用户注册啦!当前总数: " +
userRegistrationCounter.count());
}
// 订单创建时调用(钱钱钱!)
public void incrementOrderCreation(double amount) {
orderCreationCounter.increment();
System.out.println("收到新订单!金额: " + amount +
",订单总数: " + orderCreationCounter.count());
}
// 异常发生时调用(啊哦,出bug了)
public void incrementException(String exceptionType) {
exceptionCounter.increment();
System.err.println("发现bug!类型: " + exceptionType +
",bug总数: " + exceptionCounter.count());
}
// 更新活跃用户数(看看谁在摸鱼)
public void setActiveUsers(int count) {
activeUsers.set(count);
}
// 记录API响应时间(看看哪个接口在偷懒)
public void recordApiTime(long millis, String apiName) {
apiResponseTimer.record(millis, TimeUnit.MILLISECONDS);
if (millis > 1000) {
System.out.println("警告!接口 " + apiName +
" 响应缓慢,耗时: " + millis + "ms");
}
}
// 点赞时调用(收到小心心)
public void incrementLike() {
likeCounter.increment();
System.out.println("收到一个点赞!当前点赞数: " + likeCounter.count());
}
}
第5步:AOP监控切面 - 安装"全方位摄像头"
java
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 接口监控切面
* 相当于在每个接口门口安装"摄像头+计时器"
*/
@Aspect
@Component
public class MonitorAspect {
@Autowired
private BusinessMetrics businessMetrics;
// 监控所有Controller(重点监控对象)
@Pointcut("execution(* com.example.controller..*.*(..))")
public void controllerPointcut() {}
// 监控Service层(业务逻辑层)
@Pointcut("execution(* com.example.service..*.*(..))")
public void servicePointcut() {}
@Around("controllerPointcut()")
public Object monitorController(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
String methodName = joinPoint.getSignature().toShortString();
System.out.println("🎬 接口开始执行: " + methodName);
try {
Object result = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - startTime;
// 记录响应时间
businessMetrics.recordApiTime(executionTime, methodName);
System.out.println("接口执行成功: " + methodName +
",耗时: " + executionTime + "ms");
return result;
} catch (Exception e) {
// 记录异常
businessMetrics.incrementException(e.getClass().getSimpleName());
System.err.println("接口执行失败: " + methodName +
",异常: " + e.getMessage());
throw e;
}
}
@Around("servicePointcut()")
public Object monitorService(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().toShortString();
// 检查是不是重要业务方法
if (methodName.contains("UserService.register")) {
System.out.println("开始注册用户...");
} else if (methodName.contains("OrderService.create")) {
System.out.println("开始创建订单...");
}
try {
return joinPoint.proceed();
} catch (Exception e) {
System.err.println("业务方法出错: " + methodName);
businessMetrics.incrementException("ServiceException");
throw e;
}
}
}
第6步:监控告警配置 - 设置"紧急呼叫按钮"
typescript
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* 监控告警系统
* 相当于应用的"私人医生紧急呼叫"
*/
@Component
public class MonitorAlert {
@Autowired(required = false)
private JavaMailSender mailSender;
@Autowired
private BusinessMetrics businessMetrics;
private HealthIndicator databaseHealth;
// 每小时检查一次健康状态(定期体检)
@Scheduled(fixedRate = 60 * 60 * 1000)
public void healthCheck() {
System.out.println("开始定时健康检查...");
// 检查异常数(看看是不是bug泛滥)
double exceptionCount = businessMetrics.getExceptionCount();
if (exceptionCount > 100) {
sendAlert("异常数超标警告",
"系统异常数已达到 " + exceptionCount + ",快去修bug!");
}
// 检查响应时间(看看接口是不是在偷懒)
double avgResponseTime = businessMetrics.getAvgResponseTime();
if (avgResponseTime > 5000) {
sendAlert("系统响应缓慢",
"平均响应时间 " + avgResponseTime + "ms,用户要跑光了!");
}
System.out.println("健康检查完成,一切正常!");
}
// 每天发送日报(每日病情报告)
@Scheduled(cron = "0 0 18 * * ?") // 每天下午6点
public void dailyReport() {
String report = buildDailyReport();
System.out.println("生成日报:\n" + report);
if (mailSender != null) {
sendEmail("系统监控日报 - " + new Date(), report);
}
}
private String buildDailyReport() {
return """
======== 系统监控日报 ========
日期:%s
今日新增用户:%d
今日订单总数:%d
今日点赞数:%d
今日异常数:%d
平均响应时间:%.2f ms
系统健康状态:%s
============================
""".formatted(
new Date(),
businessMetrics.getTodayUserRegistrations(),
businessMetrics.getTodayOrders(),
businessMetrics.getTodayLikes(),
businessMetrics.getTodayExceptions(),
businessMetrics.getAvgResponseTime(),
getOverallHealthStatus()
);
}
private void sendAlert(String title, String message) {
System.err.println(title + ": " + message);
// 发送邮件告警(如果配置了邮件)
if (mailSender != null) {
sendEmail("[紧急]" + title, message);
}
// 这里还可以集成钉钉、企业微信、短信等告警
System.out.println("已发送告警通知!");
}
private void sendEmail(String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo("dev-team@example.com");
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
}
private String getOverallHealthStatus() {
// 综合判断系统健康状况
if (businessMetrics.getTodayExceptions() > 50) {
return "生病了,需要紧急处理";
} else if (businessMetrics.getAvgResponseTime() > 1000) {
return "有点疲惫,需要优化";
} else {
return "非常健康,继续努力";
}
}
}
第7步:可视化监控面板 - 打造"监控指挥中心"
arduino
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring Boot Admin Server
* 监控可视化面板,相当于"监控指挥中心大屏幕"
*/
@SpringBootApplication
@EnableAdminServer
public class MonitorDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(MonitorDashboardApplication.class, args);
System.out.println("""
监控面板启动成功!
访问地址: http://localhost:8080
用户名: admin
密码: admin
在这里你可以看到:
1. 所有服务的健康状态
2. 实时性能指标
3. 告警信息
4. 日志查看
5. 动态配置管理
就像有了一个全天候的监控室!
""");
}
}
三、访问监控端点
应用启动后,可以访问以下监控端点:
bash
健康检查:http://localhost:8080/actuator/health
所有指标:http://localhost:8080/actuator/metrics
Prometheus格式:http://localhost:8080/actuator/prometheus
应用信息:http://localhost:8080/actuator/info
环境变量:http://localhost:8080/actuator/env
Bean列表:http://localhost:8080/actuator/beans
映射关系:http://localhost:8080/actuator/mappings
配置属性:http://localhost:8080/actuator/configprops
四、完整配置示例
yaml
# application-monitor.yml
spring:
boot:
admin:
client:
url: http://localhost:8080
instance:
name: ${spring.application.name}
security:
user:
name: admin
password: admin123
mail:
host: smtp.example.com
port: 587
username: monitor@example.com
password: yourpassword
properties:
mail:
smtp:
auth: true
starttls:
enable: true
# 监控告警规则
monitor:
alert:
enabled: true
email:
recipients:
- dev-team@example.com
- ops-team@example.com
thresholds:
response-time: 5000 # 5秒
error-rate: 0.05 # 5%
memory-usage: 0.8 # 80%
schedules:
daily-report: "0 0 18 * * ?" # 每天18点
health-check: "0 */30 * * * ?" # 每30分钟
五、总结:监控让系统"透明化"
为什么要监控?(监控的五大好处)
- 预防胜于治疗
- 在用户投诉前发现问题
- 在系统崩溃前预警
- 就像给系统打了"疫苗"
- 快速定位问题
- 不再是"猜谜游戏"
- 精准定位问题根因
- 减少"重启试试"的次数
- 性能优化依据
- 知道哪里慢,才知道怎么优化
- 数据驱动的优化决策
- 告别"我感觉这个接口有点慢"
- 容量规划参考
- 知道系统能承受多少压力
- 合理规划服务器资源
- 避免"双十一"时系统崩溃
- 提升开发体验
- 实时了解系统状态
- 快速验证修复效果
- 减少半夜被叫起来修bug的概率
监控的最佳实践
- 分层监控:从基础设施到应用层全链路监控
- 关键指标:监控黄金指标(延迟、流量、错误、饱和度)
- 智能告警:避免告警疲劳,设置合理的阈值
- 可视化:一图胜千言,好的图表让人秒懂状态
- 持续改进:根据监控数据不断优化系统
最后
没有监控的系统就像没有仪表的飞机------飞得高不高、快不快、安不安全,全凭感觉!等到坠机了,都不知道是没油了还是引擎坏了。
给你的SpringBoot应用装上监控,就像:
- 给汽车装上了仪表盘+行车记录仪+胎压监测
- 给程序员配上了智能手环+年度体检+健康教练
- 给房子安装了烟雾报警器+摄像头+智能门锁
监控不是万能的,但没有监控是万万不能的!
现在,去给你的应用装上"健康手环",让它从此过上"透明、健康、可观测"的幸福生活吧!
温馨提示:监控虽好,也不要过度监控哦!毕竟,连上厕所都要统计时间和次数的话,系统也会感到"压力山大"的!

谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。
您的一键三连,是我更新的最大动力,谢谢
山水有相逢,来日皆可期,谢谢阅读,我们再会
我手中的金箍棒,上能通天,下能探海