当前位置: 首页 > web >正文

Spring Boot 监控:AOP vs Filter vs Java Agent

在这里插入图片描述

01前言

在 高并发 + 微服务 中,
传统 手动埋点(System.currentTimeMillis())就像用体温计量火箭速度——代码侵入、重复劳动、维护爆炸。
下文是无侵入、高精度、全链路 监控 API 耗时,全程不碰业务代码的方案!

02实战:6 种方案横向对比

在这里插入图片描述

03方案详解

方案 1:StopWatch(临时调试)
代码:

@GetMapping("/query")
public ResponseEntity<String> query() throws Exception {StopWatch stopWatch = new StopWatch(); // 创建计时器stopWatch.start(); // 开始计时TimeUnit.MILLISECONDS.sleep(new Random().nextLong(2000)); // 模拟业务stopWatch.stop(); // 结束计时System.out.printf("**方法耗时:%dms**%n", stopWatch.getTotalTimeMillis());return ResponseEntity.ok("api query...");
}

注解:

  1. StopWatch 是 Spring 提供的轻量级计时工具。
  2. 侵入性强:需手动插入到业务代码中。
  3. 适合 临时调试,生产环境 不推荐。

方案 2:AOP 切面(无侵入)
代码:

@Aspect // 声明切面
@Component
public class PerformanceAspect {private static final Logger logger = LoggerFactory.getLogger("api.timed");@Around("@annotation(org.springframework.web.bind.annotation.GetMapping)") // 拦截所有 Get 请求public Object recordExecutionTime(ProceedingJoinPoint pjp) throws Throwable {StopWatch sw = new StopWatch();sw.start();Object result = pjp.proceed(); // 执行原方法sw.stop();logger.info("**方法【{}】耗时: {}ms**", pjp.getSignature(), sw.getTotalTimeMillis());return result;}
}

注解:

  1. @Around 注解拦截所有 GetMapping 方法,零侵入。
  2. 通过 ProceedingJoinPoint 获取方法签名,精准定位慢接口。
  3. 缺点:无法监控非 Spring 管理的类(如手动 new 的对象)。

方案 3:拦截器(Controller 层统一监控)
代码:

public class TimedInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {request.setAttribute("startTime", System.currentTimeMillis()); // 记录开始时间return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {long startTime = (long) request.getAttribute("startTime");long cost = System.currentTimeMillis() - startTime;System.out.printf("**请求【%s】耗时: %dms**%n", request.getRequestURI(), cost);}
}@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new TimedInterceptor()).addPathPatterns("/api/**"); // 拦截所有 /api 下的请求}
}

注解:

  1. preHandle 在请求前记录时间,afterCompletion 在请求后计算耗时。
  2. 只适用于 Controller 层,无法监控 Service/DAO 层方法。
  3. 配置简单,适合 Web 项目快速接入。

方案 4:Filter(Servlet 级通用监控)
代码:

@Component
public class RequestTimingFilter implements Filter {private static final Logger logger = LoggerFactory.getLogger(RequestTimingFilter.class);@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;long startTime = System.nanoTime(); // 高精度计时try {chain.doFilter(request, response); // 继续处理请求} finally {long duration = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);logger.info("**[{}] {} - {}ms (Status: {})**",httpRequest.getMethod(),httpRequest.getRequestURI(),duration,((HttpServletResponse) response).getStatus());}}
}

注解:

  1. 全局生效,所有请求(包括静态资源)都会被监控。
  2. 粒度较粗,无法定位具体方法耗时。
  3. 可通过 excludePaths 过滤不需要监控的 URI。

方案 5:事件监听(零侵入全局统计)
代码:

@Component
public class TimedListener {@EventListener(ServletRequestHandledEvent.class)public void recordTimed(ServletRequestHandledEvent event) {System.err.println("**请求监控事件: " + event + "**");}
}

注解:

  1. Spring 内部事件机制,无需任何配置。
  2. 只能获取 总耗时,无法拆分各阶段耗时。
  3. 适合 快速接入,不适合精细化监控。

方案 6:Micrometer + Prometheus(可视化监控)
代码:

@RestController
public class ApiController {@Timed(value = "api.query", description = "查询业务接口") // 关键注解@GetMapping("/query")public ResponseEntity<String> query() throws Exception {TimeUnit.MILLISECONDS.sleep(new Random().nextLong(2000));return ResponseEntity.ok("api query...");}
}

配置:

# application.yml
management:endpoints:web:exposure:include: prometheus # 暴露 Prometheus 端点metrics:export:prometheus:enabled: true
Prometheus 配置:- job_name: "spring-boot-app"metrics_path: "/actuator/prometheus"static_configs:- targets: ["localhost:8080"]

注解:

  1. @Timed 注解 零侵入,自动记录耗时指标。
  2. Prometheus + Grafana 可视化展示,支持 报警规则。
  3. 缺点:需引入额外依赖,适合生产环境。

方案 7:SkyWalking(分布式全链路追踪)
启动命令:

java -javaagent:/path/skywalking-agent.jar \-Dskywalking.agent.service_name=your-app \-jar your-app.jar

注解:

  1. 无代码侵入,通过 Java Agent 自动注入。
  2. 支持 分布式链路追踪,跨服务追踪耗时。
  3. 适合微服务架构,强烈推荐!

如何选?

• 单体应用:Micrometer + Prometheus(可视化 + 报警)。
• 微服务架构:SkyWalking(全链路追踪)。
• 临时调试:Arthas(在线诊断神器)。

http://www.xdnf.cn/news/15678.html

相关文章:

  • Cadence SPB 2024软件下载及安装教程|Cadence软件安装详细步骤附下载链接
  • java如何实现打印list对象占用多大内存
  • Web开发 01
  • 【Java开发日记】详细地讲解一下如何保证线程安全性呢?
  • vue svg实现一个环形进度条组件
  • VSCODE常规设置
  • 代码随想录算法训练营65期第22天
  • 【专题十二】栈
  • 从现场出发:能源系统中的智能设备与实际落地工具解读
  • 【Java开发日记】我们来说说 LockSupport 的 park 和 unpark
  • docker--安装--原理
  • RabbitMQ概述和工作模式
  • 60个功能OfficeBox 万彩办公大师:PDF 格式转换 OCR识别免费无广告
  • mac电脑无法阅读runc源码
  • Docker容器技术讲解
  • Apache SeaTunnel详解与部署(最新版本2.3.11)
  • ether.js的calldata
  • 【基于飞浆训练车牌识别模型】
  • 【Java】【力扣】101.对称二叉树
  • Transform的重要方法
  • C++修炼:IO流
  • 关于程序=数据结构+算法这句话最近的一些思考
  • 多目标优化|HKELM混合核极限学习机+NSGAII算法工艺参数优化、工程设计优化,四目标(最大化输出y1、最小化输出y2,y3,y4),Matlab完整源码
  • WAMP允许远程访问
  • 【机器学习【6】】数据理解:数据导入、数据审查与数据可视化方法论
  • Ubuntu中man手册不全解决以及man手册中英文切换方法
  • OpenSearch SQL 查询完整指南
  • STM32-DMA
  • 数字魔方--玩转魔方的助手
  • oracle2kingbase的字段长度问题