springboot 项目某个接口响应特别慢问题排查分析

 更新时间:2025年12月08日 17:19:07   作者:ByteX  
文章描述了一个Spring Boot项目中某个接口请求日志显示耗时极短,但通过Postman发起相同请求时耗时显著增加的问题,经过排查,发现耗时主要集中在自定义的ControllerInterceptor中的logBefore方法,特别是SensitiveInfoSerialize.getJson方法,感兴趣的朋友跟随小编一起看看吧

问题现象

接口请求日志显示耗时仅为几十毫秒,但通过Postman发起相同请求时,实际耗时却高达7秒多。

[2025-12-02 09:06:27.344]-[INFO]-[http-nio-3012-exec-3]-[logId:6600b2f0-8d68-4c2c-a7b5-bce11a42e140]-[com.xxx.interceptor.ControllerInterceptor.info:63] 调用 接口://task/retry Class:com.xxx.xxx.xxx.controller.TaskController,Method:taskRetry,Request:101   
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@63bd0ef2] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@3448c914] will not be xxxd by Spring
==>  Preparing: select id, task_code, task_name, task_desc, task_execute_time, task_over_time, task_timer, file_path, status, task_type, create_name, update_name, create_date, update_date from r_task where id = ? and status = ? 
==> Parameters: 101(Integer), 4(Byte)
<==      Total: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@63bd0ef2]
[2025-12-02 09:06:27.354]-[WARN]-[http-nio-3012-exec-3]-[logId:6600b2f0-8d68-4c2c-a7b5-bce11a42e140]-[com.xxx..xxx.service.impl.RetryTaskServiceImpl.taskRetry:50]-任务重试任务查询为空,id:101
[2025-12-02 09:06:27.355]-[INFO]-[http-nio-3012-exec-3]-[logId:6600b2f0-8d68-4c2c-a7b5-bce11a42e140]-[com.xxx.interceptor.ControllerInterceptor.logReturn:81]-Class:com.xxx..xxx.controller.TaskController,Method:taskRetry,Response:{"code":"999","msg":"任务重试失败"}

postman请求示例

问题排查

先用arthas的 trace命令 确定哪块执行比较耗时

    `---[6792.636ms] org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor:intercept()
        +---[0.0061ms] org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor:getTarget() #655
        +---[0.005ms] org.springframework.aop.framework.AdvisedSupport:getInterceptorsAndDynamicInterceptionAdvice() #659
        +---[0.0079ms] org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation:<init>() #673
        +---[6792.5681ms] org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation:proceed() #673
        |   `---[10.2326ms] org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor:intercept()
        |       +---[0.0044ms] org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor:getTarget() #655
        |       +---[0.0047ms] org.springframework.aop.framework.AdvisedSupport:getInterceptorsAndDynamicInterceptionAdvice() #659
        |       +---[0.0092ms] org.springframework.aop.framework.AopProxyUtils:adaptArgumentsIfNecessary() #668
        |       +---[10.1483ms] org.springframework.cglib.proxy.MethodProxy:invoke() #669
        |       +---[0.0034ms] org.springframework.aop.framework.CglibAopProxy:access$000() #675
        |       `---[0.0031ms] org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor:releaseTarget() #680
        +---[0.0034ms] org.springframework.aop.framework.CglibAopProxy:access$000() #675
        `---[0.0025ms] org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor:releaseTarget() #680

经过断点调试,程序最终进入了自定义的ControllerInterceptor中的logBefore方法。该方法的主要逻辑相对简单,主要用于打印请求日志并对输入参数进行脱敏处理。问题出在负责参数脱敏的SensitiveInfoSerialize.getJson方法上。

通过断点跟踪发现,程序是在MethodBeforeAdviceInterceptor中执行this.advice.before这行代码时进入自定义ControllerInterceptor的。

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
    private MethodBeforeAdvice advice;
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        return mi.proceed();
    }
}

ControllerInterceptor 的logBefore

 /**
     * /**
     * 记录输入日志
     *
     * @param joinPoint
     */
    @Before(value = "controllerService()")
    public void logBefore(JoinPoint joinPoint) {
        LogUtil.bindLogId(UUID.randomUUID().toString());
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        if (ArrayUtils.isNotEmpty(args)) {
            LogHelper.info(logger, "调用", "接口:" + logTool.getServiceKey(), "Class:" + className
                    + ",Method:" + methodName + ",Request:" + SensitiveInfoSerialize.getJson(args[0]), "", "", "");
        }
    }

这段代码的核心逻辑是:

  1. 遍历 Java Bean 的所有字段
  2. 识别带有 SensitiveInfo 注解的 String 类型字段
  3. 对这些字段执行脱敏处理
  4. 对嵌套对象、数组、集合和 Map 进行递归处理

需要注意的是,这是一个内部工具类,虽然具体实现不便展示,但实际使用中存在一些需要注意的问题。

结论

根本原因是对参数进行递归的时候没有排除基本数据类型,导致对基本数据类型的字段进行递归导致耗时很长。

所以使用递归时要特别注意退出条件,不然可能会导致耗时很长甚至栈溢出。

到此这篇关于springboot 项目某个接口响应特别慢排查的文章就介绍到这了,更多相关springboot接口响应慢内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Logback在SpringBoot项目中实现日志记录功能

    使用Logback在SpringBoot项目中实现日志记录功能

    日志记录是每个应用程序中不可或缺的一部分,尤其是对于大型应用,日志能够帮助我们追踪系统的状态、分析故障、监控性能等,在Java项目中, Logback是一个非常流行的日志框架,广泛用于SpringBoot项目中,本文给大家介绍了如何使用Logback在SpringBoot项目中实现日志记
    2025-11-11
  • java异步编程的7种实现方式小结

    java异步编程的7种实现方式小结

    异步处理的实现方式有很多种,常见多线程,消息中间件,发布订阅的广播模式,本文就详细的介绍java异步编程的7种实现方式,感兴趣的可以了解一下
    2023-03-03
  • 微服务eureka和nacos案例详解

    微服务eureka和nacos案例详解

    这篇文章主要介绍了微服务eureka和nacos,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • 详解Maven项目Dependencies常见报错及解决方案

    详解Maven项目Dependencies常见报错及解决方案

    这篇文章主要介绍了详解Maven项目Dependencies常见报错及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 基于springboot 长轮询的实现操作

    基于springboot 长轮询的实现操作

    这篇文章主要介绍了基于springboot 长轮询的实现操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • JavaSE详细讲解异常语法

    JavaSE详细讲解异常语法

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等
    2022-05-05
  • SpringBoot中验证用户上传的图片资源的方法

    SpringBoot中验证用户上传的图片资源的方法

    这篇文章主要介绍了在SpringBoot中验证用户上传的图片资源,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Vue.Js及Java实现文件分片上传代码实例

    Vue.Js及Java实现文件分片上传代码实例

    这篇文章主要介绍了Vue.Js及Java实现文件分片上传代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • @Transactional用法详解与事务避坑指南

    @Transactional用法详解与事务避坑指南

    这篇文章主要介绍了@Transactional用法与事务避坑指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-10-10
  • 详解Java sort()数组排序(升序和降序)

    详解Java sort()数组排序(升序和降序)

    这篇文章主要介绍了详解Java sort()数组排序(升序和降序),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01

最新评论