并发情况下advice记录日志错乱如何解决?

发布于 2022-09-12 23:16:22 字数 2076 浏览 14 评论 0

问题描述

Springboot项目,在频繁调用多个接口时,advice里记录的日志会错乱。现象是这样的:在请求量大的时候,A请求正在执行未执行完毕,B请求进入并报了异常,B请求的错误日志被A记录了下来,同时A请求也莫名其妙的调用也失败了。请问如何解决?

相关代码

@Aspect
@Component
@EnableAspectJAutoProxy
public class AdviceApi {
  @Autowired
    private LogAnalyseService logAnalyseService;

    // 记录日志的对象Bean
    @Bean
    public LogChannelCall getBean() {
        return new LogChannelCall();
    }
    // 统计调用时长
    private ThreadLocal<Long> startTime = new ThreadLocal<>();

    @Pointcut("execution(* com.api.controller.*.*(..))")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void before() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        String userId = request.getParameter("userId");
        String remoteAddr = request.getRemoteAddr();
     
        logChannelCall.setUserId(userId);
        logChannelCall.setIp(remoteAddr);
        startTime.set(System.currentTimeMillis());
    }

    @After("pointcut()")
    public void after() {
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        boolean successful = response.getStatus() == 200;
        logChannelCall.setSuccessful(successful);
    }

    @AfterReturning("pointcut()")
    public void afterReturning() {
        logChannelCall.setSuccessful(true);
        logChannelCall.setResponseTime(System.currentTimeMillis() - startTime.get());
        logAnalyseService.insertV3Log(logChannelCall);
    }

    @AfterThrowing(throwing = "ex", pointcut = "pointcut()")
    public void afterThrowing(Exception ex) {
        logChannelCall.setSuccessful(false);
        logChannelCall.setReason(ex.getMessage());
        logChannelCall.setResponseTime(System.currentTimeMillis() - startTime.get());
        // 执行插入日志操作
        logAnalyseService.insertV3Log(logChannelCall);
    }
}

你期待的结果是什么?实际看到的错误信息又是什么?

请大家帮我分析一下,首先如何解决日志错乱的问题、其次,为何B请求错误会导致A请求也失败呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

写给空气的情书 2022-09-19 23:16:22

经过问题评论里的友♂ 好讨论,看来也不是个啥大难题,你需要的形参参数数组,这样应该可以达到你想要对应的效果了叭

@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) {
     Signature signature = joinPoint.getSignature();
     MethodSignature methodSignature = (MethodSignature) signature;
     // 方法参数值
     Object[] args = joinPoint.getArgs();
     // 你要的对应参数名字
     String[] parameterNames = methodSignature.getParameterNames();
     // TODO other
}
走野 2022-09-19 23:16:22

你的日志记录对象并非线程安全对象,改为线程安全对象应该就不会出现这样的问题。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文