Spring?Boot?如何通過ServletRequestHandledEvent事件實(shí)現(xiàn)接口請求的性能監(jiān)控
概述
在Spring框架中,監(jiān)控接口請求的性能可以通過ServletRequestHandledEvent
事件實(shí)現(xiàn)。這種方法簡單有效,能夠幫助開發(fā)者實(shí)時(shí)跟蹤和分析請求的性能。
1. ServletRequestHandledEvent事件
ServletRequestHandledEvent
是Spring中的一個(gè)事件類,它在請求處理完成后發(fā)布,包含了請求的詳細(xì)信息,如客戶端地址、請求URL、請求方法和處理時(shí)間。使用這個(gè)事件可以輕松地監(jiān)控和記錄每個(gè)請求的性能數(shù)據(jù)。
2. 實(shí)現(xiàn)步驟
下面是如何通過TimeCountListener
實(shí)現(xiàn)接口請求性能監(jiān)控的步驟:
創(chuàng)建監(jiān)聽器類
實(shí)現(xiàn)ApplicationListener<ServletRequestHandledEvent>
接口并覆蓋onApplicationEvent
方法:
@Component public class TimeCountListener implements ApplicationListener<ServletRequestHandledEvent> { @Override public void onApplicationEvent(ServletRequestHandledEvent event) { Throwable failureCause = event.getFailureCause(); if (failureCause != null) { System.err.printf("錯(cuò)誤原因: %s%n", failureCause.getMessage()); } System.err.println("========================================"); System.err.printf("請求客戶端地址:%s\n請求URL: %s\n請求Method: %s\n請求耗時(shí): %d毫秒%n", event.getClientAddress(), event.getRequestUrl(), event.getMethod(), event.getProcessingTimeMillis()); System.err.println("========================================"); } }
注冊監(jiān)聽器
使用@Component
注解標(biāo)記TimeCountListener
,Spring會(huì)自動(dòng)將其注冊為應(yīng)用程序的事件監(jiān)聽器。
3. 優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 簡單易用:無需對業(yè)務(wù)代碼進(jìn)行侵入式修改,只需創(chuàng)建監(jiān)聽器類。
- 準(zhǔn)確性高:Spring會(huì)在請求處理完成后發(fā)布事件,記錄的時(shí)間較為準(zhǔn)確。
- 低侵入性:與業(yè)務(wù)邏輯代碼解耦,易于維護(hù)和擴(kuò)展。
缺點(diǎn):
- 性能開銷:盡管開銷較小,但記錄和處理事件仍然會(huì)增加系統(tǒng)的負(fù)擔(dān)。
- 事件丟失:在高并發(fā)或系統(tǒng)異常情況下,事件可能會(huì)丟失或記錄不全。
4. 測試與驗(yàn)證
要測試TimeCountListener
的有效性,可以創(chuàng)建一個(gè)測試接口,并在其上執(zhí)行不同的請求。以下是一個(gè)簡單的測試示例:
package com.artisan.controller; import com.artisan.domain.Artisan; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Arrays; /** * @author 小工匠 * @version 1.0 * @description: TODO * @date 2021/1/9 22:39 * @mark: show me the code , change the world */ @RestController public class ArtisanController { @RequestMapping("/hi") public String test() { return "小工匠 每日一博"; } @RequestMapping("/hi2") public Object test2() { Artisan artisan = new Artisan(); artisan.setName("小工匠"); artisan.setAge(18); artisan.setHobbies(Arrays.asList("code", "sleep", "study")); return artisan; } /** * 處理GET請求,返回自定義的響應(yīng) * 該方法通過@RequestParam接收id和kw作為查詢參數(shù),然后構(gòu)建一個(gè)自定義的響應(yīng)返回給調(diào)用者 * 主要用于演示如何在Spring MVC中返回自定義的響應(yīng)體和響應(yīng)頭 * * @param id 需要查詢的ID * @return 自定義的響應(yīng)對象,包含響應(yīng)體、響應(yīng)頭和HTTP狀態(tài)碼 */ @GetMapping("/hi3") public Object index(Long id) { // 創(chuàng)建HttpHeaders對象,用于自定義響應(yīng)頭 HttpHeaders headers = new HttpHeaders(); // 向響應(yīng)頭中添加自定義的版本信息 headers.add("x-version", "v1"); // 創(chuàng)建響應(yīng)對象,設(shè)置響應(yīng)體、響應(yīng)頭和HTTP狀態(tài)碼 ResponseEntity<Object> response = new ResponseEntity<>( // 構(gòu)建響應(yīng)體內(nèi)容,格式化輸出id和kw String.format("id = %d", id), headers, HttpStatus.valueOf(200) ); // 返回自定義的響應(yīng)對象 return response; } }
訪問 http://localhost:7777/hi3?id=1
小結(jié)
使用Spring的ServletRequestHandledEvent
進(jìn)行接口請求性能監(jiān)控是一種簡單且有效的方法。通過創(chuàng)建一個(gè)監(jiān)聽器,可以輕松地獲取請求的詳細(xì)性能信息,而無需對現(xiàn)有代碼進(jìn)行重大修改。然而,這種方法也有其局限性,如輕微的性能開銷和潛在的事件丟失問題。
其他方案
1. 自定義攔截器
概述:自定義攔截器可以用來在請求處理的不同階段(如請求前、請求后、請求完成后)添加額外的邏輯。
實(shí)現(xiàn)步驟:
- 實(shí)現(xiàn)
HandlerInterceptor
接口,覆蓋其中的方法,如preHandle
、postHandle
、和afterCompletion
。 - 在這些方法中記錄請求開始時(shí)間、結(jié)束時(shí)間,計(jì)算處理時(shí)間。
- 將攔截器注冊到Spring MVC配置中。
示例代碼:
public class PerformanceInterceptor implements HandlerInterceptor { private static final Logger logger = LoggerFactory.getLogger(PerformanceInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { request.setAttribute("startTime", System.currentTimeMillis()); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { long startTime = (Long) request.getAttribute("startTime"); long endTime = System.currentTimeMillis(); long executeTime = endTime - startTime; logger.info("請求URL: {},耗時(shí): {} ms", request.getRequestURI(), executeTime); } }
優(yōu)點(diǎn):能夠靈活控制每個(gè)請求的處理過程,精確測量請求耗時(shí)。
2. 性能監(jiān)控平臺(tái)
概述:使用專用的性能監(jiān)控平臺(tái)可以提供豐富的可視化和分析功能,幫助識(shí)別性能瓶頸。
常用工具:
- Prometheus和Grafana:Prometheus用于數(shù)據(jù)收集和監(jiān)控,Grafana用于數(shù)據(jù)可視化和告警設(shè)置。
- New Relic:提供全面的應(yīng)用性能監(jiān)控,支持多種編程語言和框架。
- AppDynamics:實(shí)時(shí)監(jiān)控應(yīng)用性能,幫助快速定位問題。
集成步驟:
在應(yīng)用中集成相應(yīng)的監(jiān)控客戶端庫。配置監(jiān)控指標(biāo)和數(shù)據(jù)收集策略。在監(jiān)控平臺(tái)上設(shè)置儀表板,實(shí)時(shí)觀察應(yīng)用性能數(shù)據(jù)。
優(yōu)點(diǎn):提供全面的性能數(shù)據(jù)分析和可視化,支持告警和歷史數(shù)據(jù)回溯。
3. 使用Spring Boot Actuator
概述:Spring Boot Actuator提供了一組生產(chǎn)級的監(jiān)控功能,包括指標(biāo)、健康檢查、審計(jì)等。
集成步驟:
- 在Spring Boot項(xiàng)目中引入
spring-boot-starter-actuator
依賴。 - 配置
application.properties
啟用所需的監(jiān)控端點(diǎn)。 - 使用內(nèi)置的HTTP端點(diǎn)或JMX監(jiān)控應(yīng)用的健康狀況和性能指標(biāo)。
示例配置:
management.endpoints.web.exposure.include=*
優(yōu)點(diǎn):集成簡單,提供豐富的監(jiān)控端點(diǎn),適合Spring Boot應(yīng)用。
4. APM工具
概述:應(yīng)用性能管理(APM)工具可以幫助全面監(jiān)控和分析應(yīng)用性能,識(shí)別瓶頸并優(yōu)化性能。
常用工具:
- Elastic APM:與Elastic Stack整合,提供應(yīng)用性能監(jiān)控和日志管理。
- Datadog:支持云原生應(yīng)用監(jiān)控,提供全面的性能數(shù)據(jù)。
- Skywalking:支持云原生應(yīng)用監(jiān)控,提供全面的性能數(shù)據(jù)。
優(yōu)點(diǎn):提供詳細(xì)的性能分析報(bào)告和可視化,易于識(shí)別和解決性能問題。
到此這篇關(guān)于Spring Boot 如何通過ServletRequestHandledEvent事件實(shí)現(xiàn)接口請求的性能監(jiān)控的文章就介紹到這了,更多相關(guān)Spring Boot接口請求的性能監(jiān)控內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IntelliJ IDEA 部署 Web 項(xiàng)目,看這一篇夠了!
這篇文章主要介紹了IntelliJ IDEA 部署 Web 項(xiàng)目的圖文教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05@Slf4j?如何實(shí)現(xiàn)日志輸入到外部文件
這篇文章主要介紹了@Slf4j?如何實(shí)現(xiàn)日志輸入到外部文件,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12SpringBoot中application.properties與application.yml區(qū)別小結(jié)
本文主要介紹了SpringBoot中application.properties與application.yml區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-10-10Linux部署springboot項(xiàng)目彩色日志打印方式
這篇文章主要介紹了Linux部署springboot項(xiàng)目彩色日志打印方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04解決springboot使用logback日志出現(xiàn)LOG_PATH_IS_UNDEFINED文件夾的問題
這篇文章主要介紹了解決springboot使用logback日志出現(xiàn)LOG_PATH_IS_UNDEFINED文件夾的問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04java_IO向文件中寫入和讀取內(nèi)容代碼實(shí)例
這篇文章主要介紹了java_IO向文件中寫入和讀取內(nèi)容,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03Java基于redis實(shí)現(xiàn)分布式鎖代碼實(shí)例
這篇文章主要介紹了Java基于redis實(shí)現(xiàn)分布式鎖代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04