Spring Boot 實(shí)戰(zhàn):通過(guò) Agent 統(tǒng)計(jì)接口調(diào)用耗時(shí)
隨著微服務(wù)架構(gòu)的普及,API的性能監(jiān)控變得愈發(fā)重要。對(duì)于Spring Boot應(yīng)用,記錄接口耗時(shí)不僅可以幫助我們優(yōu)化性能,還能在出現(xiàn)問(wèn)題時(shí)快速定位。接口耗時(shí)直接影響用戶體驗(yàn)和系統(tǒng)性能,通過(guò)記錄和分析接口耗時(shí),我們可以識(shí)別性能瓶頸并進(jìn)行優(yōu)化,同時(shí)生成統(tǒng)計(jì)報(bào)表來(lái)監(jiān)控接口健康狀態(tài)。
Agent介紹
在Spring Boot中,我們通常通過(guò)幾種方式來(lái)統(tǒng)計(jì)接口調(diào)用耗時(shí),其中一種方法是使用Agent。Agent是一種工具,可以插入到Java虛擬機(jī)(JVM)中,監(jiān)控并收集應(yīng)用運(yùn)行時(shí)的各種信息,包括接口調(diào)用耗時(shí)。然而,在Spring Boot中,更常見(jiàn)且簡(jiǎn)便的方式是使用Actuator、AOP或過(guò)濾器來(lái)實(shí)現(xiàn)這一功能。盡管本文主題是通過(guò)Agent進(jìn)行統(tǒng)計(jì),但為了更好地理解和對(duì)比,我們也會(huì)簡(jiǎn)要介紹Spring Boot Actuator及其他方法。
Spring Boot Actuator:Actuator是Spring Boot提供的對(duì)應(yīng)用的自省和監(jiān)控功能,如健康檢查、審計(jì)、指標(biāo)收集、HTTP跟蹤等。通過(guò)Actuator,我們可以輕松地采集應(yīng)用的內(nèi)部信息,并暴露給外部的模塊,支持HTTP和JMX,還可以與一些第三方監(jiān)控系統(tǒng)(如Prometheus)整合。
盡管Actuator不是嚴(yán)格意義上的Agent,但它提供了一種輕量級(jí)的方式來(lái)監(jiān)控Spring Boot應(yīng)用,并且與Spring Boot生態(tài)緊密結(jié)合。
代碼思路
1. 使用AOP統(tǒng)計(jì)接口調(diào)用耗時(shí)
AOP(面向切面編程)是一種編程范式,允許我們將橫切關(guān)注點(diǎn)(如日志記錄、事務(wù)管理等)與業(yè)務(wù)邏輯代碼分離。在Spring Boot中,我們可以使用AOP來(lái)攔截接口調(diào)用,并記錄其耗時(shí)。
步驟:
① 引入依賴:在pom.xml中引入AOP相關(guān)的依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
② 創(chuàng)建切面類:定義一個(gè)切面類,利用@Around注解來(lái)攔截請(qǐng)求方法。
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() + " 耗時(shí): " + executionTime + " 毫秒");
return proceed;
}
}
③ 測(cè)試接口:創(chuàng)建一個(gè)簡(jiǎn)單的REST控制器來(lái)測(cè)試耗時(shí)統(tǒng)計(jì)功能。
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 {
// 模擬耗時(shí)操作
Thread.sleep(200);
return "測(cè)試成功";
}
}
訪問(wèn)/test接口時(shí),控制臺(tái)將會(huì)打印該接口的執(zhí)行耗時(shí)信息。
2. 使用Spring Boot Actuator
雖然Actuator不是Agent,但它提供了豐富的監(jiān)控功能,可以與其他監(jiān)控系統(tǒng)結(jié)合使用。
步驟:
① 引入依賴:在pom.xml中添加Actuator的starter。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
② 訪問(wèn)端點(diǎn):添加依賴后,啟動(dòng)服務(wù),通過(guò)請(qǐng)求查看暴露的端點(diǎn),如http://localhost:9099/actuator。
③ 配置端點(diǎn):在application.yml中配置需要暴露的端點(diǎn)。
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
3. 使用過(guò)濾器統(tǒng)計(jì)接口調(diào)用耗時(shí)
另一種方法是實(shí)現(xiàn)一個(gè)自定義的過(guò)濾器來(lái)記錄接口訪問(wèn)日志及請(qǐng)求耗時(shí)。
步驟:
① 定義過(guò)濾器類:實(shí)現(xiàn)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地址的邏輯
}
}
② 啟用過(guò)濾器:在啟動(dòng)類上通過(guò)@ServletComponentScan注解指明該過(guò)濾器。
@SpringBootApplication
@ServletComponentScan("com.example.demo")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
總結(jié)
在Spring Boot中,通過(guò)AOP、Actuator或自定義過(guò)濾器等方式,我們可以有效地統(tǒng)計(jì)接口調(diào)用耗時(shí),并進(jìn)行性能監(jiān)控。AOP提供了一種優(yōu)雅且非侵入性的方式來(lái)攔截和記錄接口調(diào)用耗時(shí),而Actuator則提供了豐富的監(jiān)控功能,可以與第三方監(jiān)控系統(tǒng)結(jié)合使用。自定義過(guò)濾器則提供了更靈活的控制,適用于特定的監(jiān)控需求。這些方法各有優(yōu)劣,開(kāi)發(fā)者可以根據(jù)實(shí)際需求和項(xiàng)目特點(diǎn)選擇合適的方式進(jìn)行實(shí)現(xiàn)。