Spring Boot 實戰:通過 Agent 統計接口調用耗時
隨著微服務架構的普及,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來攔截接口調用,并記錄其耗時。
步驟:
① 引入依賴:在pom.xml中引入AOP相關的依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
② 創建切面類:定義一個切面類,利用@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;
}
}
③ 測試接口:創建一個簡單的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,但它提供了豐富的監控功能,可以與其他監控系統結合使用。
步驟:
① 引入依賴:在pom.xml中添加Actuator的starter。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
② 訪問端點:添加依賴后,啟動服務,通過請求查看暴露的端點,如http://localhost:9099/actuator。
③ 配置端點:在application.yml中配置需要暴露的端點。
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
3. 使用過濾器統計接口調用耗時
另一種方法是實現一個自定義的過濾器來記錄接口訪問日志及請求耗時。
步驟:
① 定義過濾器類:實現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地址的邏輯
}
}
② 啟用過濾器:在啟動類上通過@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則提供了豐富的監控功能,可以與第三方監控系統結合使用。自定義過濾器則提供了更靈活的控制,適用于特定的監控需求。這些方法各有優劣,開發者可以根據實際需求和項目特點選擇合適的方式進行實現。