Spring Boot实战:通过Agent统计接口调用耗时

科技   2024-11-09 11:34   河北  


前言

随着微服务架构的普及,API的性能监控变得愈发重要。对于Spring Boot应用,记录接口耗时不仅可以帮助我们优化性能,还能在出现问题时快速定位。接口耗时直接影响用户体验和系统性能,通过记录和分析接口耗时,我们可以识别性能瓶颈并进行优化,同时生成统计报表来监控接口健康状态。

Agent介绍

在Spring Boot中,我们通常通过几种方式来统计接口调用耗时,其中一种方法是使用Agent。Agent是一种工具,可以插入到Java虚拟机(JVM)中,监控并收集应用运行时的各种信息,包括接口调用耗时。然而,在Spring Boot中,更常见且简便的方式是使用Actuator、AOP或过滤器来实现这一功能。尽管本文主题是通过Agent进行统计,但为了更好地理解和对比,我们也会简要介绍Spring Boot Actuator及其他方法。

Spring Boot Actuator
Actuator是Spring Boot提供的对应用的自省和监控功能,如健康检查、审计、指标收集、HTTP跟踪等。通过Actuator,我们可以轻松地采集应用的内部信息,并暴露给外部的模块,支持HTTP和JMX,还可以与一些第三方监控系统(如Prometheus)整合。

尽管Actuator不是严格意义上的Agent,但它提供了一种轻量级的方式来监控Spring Boot应用,并且与Spring Boot生态紧密结合。


代码思路

1. 使用AOP统计接口调用耗时

AOP(面向切面编程)是一种编程范式,允许我们将横切关注点(如日志记录、事务管理等)与业务逻辑代码分离。在Spring Boot中,我们可以使用AOP来拦截接口调用,并记录其耗时。

步骤

  1. 引入依赖:在pom.xml中引入AOP相关的依赖。


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. 创建切面类:定义一个切面类,利用@Around注解来拦截请求方法。

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class PerformanceAspect {

    @Around("execution(* com.example.demo.controller.*.*(..))")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long executionTime = System.currentTimeMillis() - start;
        System.out.println("方法: " + joinPoint.getSignature() + " 耗时: " + executionTime + " 毫秒");
        return proceed;
    }
}
  1. 测试接口:创建一个简单的REST控制器来测试耗时统计功能。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping("/test")
    public String test() throws InterruptedException {
        // 模拟耗时操作
        Thread.sleep(200);
        return "测试成功";
    }
}

访问/test接口时,控制台将会打印该接口的执行耗时信息。

2. 使用Spring Boot Actuator

虽然Actuator不是Agent,但它提供了丰富的监控功能,可以与其他监控系统结合使用。

步骤

  1. 引入依赖:在pom.xml中添加Actuator的starter。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. 访问端点:添加依赖后,启动服务,通过请求查看暴露的端点,如http://localhost:9099/actuator

  2. 配置端点:在application.yml中配置需要暴露的端点。

management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: always

3. 使用过滤器统计接口调用耗时

另一种方法是实现一个自定义的过滤器来记录接口访问日志及请求耗时。

步骤

  1. 定义过滤器类:实现javax.servlet.Filter接口。

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Slf4j
@WebFilter(filterName = "ApiAccessFilter", urlPatterns = "/*")
public class ApiAccessFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        long start = System.currentTimeMillis();
        log.info("[Api Access] start. uri: {}, method: {}, client: {}", request.getRequestURI(), request.getMethod(), getClientIp(request));
        filterChain.doFilter(servletRequest, servletResponse);
        log.info("[Api Access] end. duration: {}ms", System.currentTimeMillis() - start);
    }

    @Override
    public void destroy() {
    }

    private String getClientIp(HttpServletRequest request) {
        // 获取客户端IP地址的逻辑
    }
}
  1. 启用过滤器:在启动类上通过@ServletComponentScan注解指明该过滤器。

@SpringBootApplication
@ServletComponentScan("com.example.demo")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

总结

在Spring Boot中,通过AOP、Actuator或自定义过滤器等方式,我们可以有效地统计接口调用耗时,并进行性能监控。AOP提供了一种优雅且非侵入性的方式来拦截和记录接口调用耗时,而Actuator则提供了丰富的监控功能,可以与第三方监控系统结合使用。自定义过滤器则提供了更灵活的控制,适用于特定的监控需求。这些方法各有优劣,开发者可以根据实际需求和项目特点选择合适的方式进行实现。



Java技术前沿
专注分享Java技术,包括但不限于 SpringBoot,SpringCloud,Docker,消息中间件等。
 最新文章