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.pswp.cn/diannao/92222.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/92222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Android的电子记账本系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业多年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…

7月17日日记

结束了数学建模之后的这两天一直在紧张的复习&#xff0c;但是说实话效率有点低&#xff0c;因为可能觉得自己找到了两个小时速成课&#xff0c;觉得无所谓了&#xff0c;所以有点放松了。在宿舍杰哥和林雨城却一直在复习&#xff0c;感觉他们的微积分和线性代数复习的都比我好…

Linux下SPI设备驱动开发

一.SPI协议介绍1.硬件连接介绍引脚含义&#xff1a;DO(MOSI)&#xff1a;Master Output, Slave Input&#xff0c;SPI主控用来发出数据&#xff0c;SPI从设备用来接收数据。DI(MISO)&#xff1a;Master Input, Slave Output&#xff0c;SPI主控用来发出数据&#xff0c;SPI从设…

用Dify构建气象智能体:从0到1搭建AI工作流实战指南

作为一名Agent产品经理,我最近在负责气象智能体的建设项目。传统气象服务面临三大痛点:数据孤岛严重(气象局API、卫星云图、地面观测站等多源数据格式不一)、响应链路长(从数据采集到预警发布需人工介入多个环节)、交互体验单一(用户只能被动接收标准化预警,无法个性化…

Android NDK ffmpeg 音视频开发实战

文章目录接入FFmpeg1.下载FFmpeg 源码2.编译FFmpeg.so库异常处理3.自定义FFmpeg交互so库创建4.配置CMakeLists.txt5.CMakeLists.txt 环境配置6.Native与Java层调用解码器准备接入FFmpeg 1.下载FFmpeg 源码 FFmpeg官网地址 2.编译FFmpeg.so库 移动 FFmpeg 源码文件夹至 Andr…

使用 go-redis-entraid 实现 Entra ID 无密钥认证

1、依赖与安装 步骤命令说明安装&#xff08;或升级&#xff09; go-redis v9.9go get github.com/redis/go-redis/v9latestentraid 必须 ≥ 9.9.0安装 go-redis-entraidgo get github.com/redis/go-redis-entraid自动拉取 transit 依赖 2、认证方式一览 方式说明创建 Stream…

window上docker安装RabbitMQ

1、要进http://localhost:15672管理页面需要安装management版本2、搜索镜像并pull3、启动镜像时将端口映射出来4、启动成功&#xff0c;点击可查看日志详情&#xff0c;浏览器访问5、直接使用guest/guest登录会报错User can only log in via localhost解决办法有两个&#xff1…

异世界历险之数据结构世界(排序(插入,希尔,堆排))

前言 介绍 插入排序 基本知识&#xff1a; 直接插入排序是一种简单的插入排序法&#xff0c;其基本思想是&#xff1a; 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为止&#xff0c;得到一个新的有序序列 直接插入…

oracle 数据库中,将几张表的数据按指定日期范围实时同步至同一个数据库的备份表中。

以下是一个Oracle数据库中实现表数据按指定日期范围实时同步至备份表的解决方案。这个方案使用存储过程和触发器组合实现&#xff1a; 1. 创建备份表结构 首先需要为每张需要备份的表创建对应的备份表&#xff0c;结构与原表相同&#xff1a; -- 为原表创建备份表&#xff08;示…

电脑网络连接正常,微信、QQ能正常使用,但无法访问网页?DNS问题的解决方案和背后原理。

文章目录1. 问题背景2. 解决方案2.1 手动刷新DNS2.1.1 Windows版本2.1.2 Mac版本2.2 手动设置DNS服务器2.2.1 Windows版2.2.2 Mac版2.3 其他解决方案3. DNS是什么&#xff1f;3.1 详细解释DNS3.1.1 A distributed, hierarchical database&#xff08;一个分布式和分层数据库结构…

【HTML】图片比例和外部div比例不一致,最大程度占满

图片比例和外部div比例不一致&#xff0c;最大程度占满&#xff0c;并且图片比例不变 其中1.jpg,2.jpg,1.html在同一目录 |-----|- 1.jpg|- 2.jpg|- 1.html1.jpg2.jpg<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /&g…

如何使用python网络爬虫批量获取公共资源数据技术

如何快速批量地获取海量公共资源数据决定了科研的效率。Python网络爬虫是快速批量获取网络数据的重要手段&#xff0c;它按照发送请求、获得页面、解析页面、下载内容、储存内容等流程&#xff1f; 一&#xff1a;Python软件的安装及入门1 Python软件安装及入门1)Anaconda软件安…

Kiro vs Cursor: AI IDE 终极对比指南

概述 随着生成式 AI 革命性地改变了我们编写代码的方式&#xff0c;新一代 AI 驱动的集成开发环境 (IDE) 正在崛起。Kiro 和 Cursor 代表了这一运动的前沿&#xff0c;但它们采用了截然不同的方法。 核心理念对比 特性AWS KiroCursor核心理念结构化开发流程 (Spec-driven)对…

Python获取网页乱码问题终极解决方案 | Python爬虫编码处理指南

在Python网络爬虫开发中&#xff0c;乱码是最常见的问题之一。本文将深入探讨乱码产生的原因&#xff0c;并提供多种有效的解决方案&#xff0c;帮助您彻底解决Python获取网页内容时的乱码问题。常见网页编码格式编码类型使用场景Python解码方式UTF-8现代网站标准编码.decode(u…

Android MTK平台预置多张静态壁纸

执行 adb shell pm list package -f wallpaper 命令&#xff0c;查看壁纸应用路径&#xff1a; /product/app/MtkWallpaperPicker/MtkWallpaperPicker.apkcom.android.wallpaperpicker 结果中带 Mtk 就可确定MTK有对应用进行重构。其源码路径在 vendor/mediatek/proprietary/…

基于Django的个人博客系统开发(开题报告)

毕业论文(设计)开题报告论文(设计)题目 基于Django的个人博客系统开发 1.选题目的和意义 随着云服务器的普及化以及编程培训机构大量涌现,学习网站开发技术以及编程技术,通过租用个人云服务器部署代码,构建个人博客网站,创建学习文档,记录学习过程,与他人交流技术学…

C++ 分配内存释放内存

C 分配内存释放内存一、new、delete、malloc和free最简单的分配内存自定义对象分配和释放内存二、new、delete与虚析构的问题三、一维、二维、多维数值创建和释放一维二维多维四、new的缺点以及连续内存的优点一、new、delete、malloc和free 最简单的分配内存 int* p_m (int*…

奥比中光深度相机开发

一、开发环境准备 1.1 硬件要求 奥比中光深度相机&#xff08;如Astra Pro、Gemini等&#xff09;USB 3.0接口&#xff08;确保数据传输稳定&#xff09;支持OpenGL的显卡&#xff08;可选&#xff0c;用于点云可视化&#xff09; 1.2 软件环境 SDK安装&#xff1a; 从奥比…

标题 “Python 网络爬虫 —— selenium库驱动浏览器

一、Selenium 库核心认知 Selenium 库是 Web 应用程序测试与自动化操作的利器 &#xff0c;能驱动浏览器&#xff08;如 Edge、Firefox 等&#xff09;执行点击、输入、打开、验证等操作 。与 Requests 库差异显著&#xff1a;Requests 库仅能获取网页原始代码&#xff0c;而 …

从实践出发--探究C/C++空类的大小,真的是1吗?

文章目录测试代码VS2022正常运行编译失败GCC总结Author: NemaleSu Data: 2025/07/21 测试环境&#xff1a; Win11&#xff1a;VS2022Ubuntu22.04&#xff1a;gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 相信众多cpper听过太多书籍、视频、文档、博客等资料&#xff0c;说C/C…