SpringBoot監(jiān)控Tomcat活動(dòng)線(xiàn)程數(shù)來(lái)判斷是否完成請(qǐng)求處理方式
SpringBoot監(jiān)控Tomcat活動(dòng)線(xiàn)程數(shù)來(lái)判斷是否完成請(qǐng)求處理
最近項(xiàng)目中有一個(gè)需求,需要判斷應(yīng)用的請(qǐng)求是否已經(jīng)處理完畢,想了一下,打算通過(guò)定時(shí)任務(wù)定時(shí)監(jiān)控Tomcat的活動(dòng)線(xiàn)程數(shù)來(lái)實(shí)現(xiàn)。
編碼實(shí)現(xiàn)
新建一個(gè)SpringBoot工程,添加定時(shí)任務(wù)定時(shí)監(jiān)控,代碼如下:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component public class TomcatMonitor { ? ? private Logger logger = LoggerFactory.getLogger(getClass()); ? ? @Autowired ? ? ServletWebServerApplicationContext applicationContext; ? ? @Scheduled(cron = "*/1 * * * * ?") ? ? public void execute() { ? ? ? ? TomcatWebServer webServer = (TomcatWebServer) applicationContext.getWebServer(); ? ? ? ? String tomcatInfo = webServer.getTomcat().getConnector().getProtocolHandler().getExecutor().toString(); ? ? ? ? System.out.println("tomcatInfo: " + tomcatInfo); ? ? } }
測(cè)試
新建一個(gè)測(cè)試請(qǐng)求類(lèi),代碼如下:
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.TimeUnit; @RestController public class TestController { ? ? @RequestMapping("/test") ? ? public String test() { ? ? ? ? try { ? ? ? ? ? ? TimeUnit.SECONDS.sleep(2); ? ? ? ? } catch (InterruptedException e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? System.out.println("complete OK"); ? ? ? ? return "OK"; ? ? } }
啟動(dòng)項(xiàng)目:
tomcatInfo: org.apache.tomcat.util.threads.ThreadPoolExecutor@49355b92[Running, pool size = 10, active threads = 0, queued tasks = 0, completed tasks = 0]
tomcatInfo: org.apache.tomcat.util.threads.ThreadPoolExecutor@49355b92[Running, pool size = 10, active threads = 0, queued tasks = 0, completed tasks = 0]
訪問(wèn)測(cè)試接口,觀察Tomcat線(xiàn)程池變化:
tomcatInfo: org.apache.tomcat.util.threads.ThreadPoolExecutor@49355b92[Running, pool size = 10, active threads = 1, queued tasks = 0, completed tasks = 0]
complete OK
tomcatInfo: org.apache.tomcat.util.threads.ThreadPoolExecutor@49355b92[Running, pool size = 10, active threads = 0, queued tasks = 0, completed tasks = 2]
可以看到,當(dāng)有請(qǐng)求處理時(shí),Tomcat的活動(dòng)線(xiàn)程數(shù)不為0,處理完成以后回歸到0,所以可以通過(guò)活動(dòng)線(xiàn)程數(shù)判斷當(dāng)前Tomcat是否有請(qǐng)求還在處理,當(dāng)然,應(yīng)用到實(shí)際業(yè)務(wù)中,還有需要完善的地方。
Tomcat線(xiàn)程數(shù)占滿(mǎn)而導(dǎo)致的線(xiàn)上事故
事故表現(xiàn)形式
昨天下午4點(diǎn)多的時(shí)候,有同學(xué)反映說(shuō),某個(gè)服務(wù)響應(yīng)時(shí)間過(guò)長(zhǎng),懷疑是負(fù)載均衡的問(wèn)題。
排查過(guò)程
1,查看阿里云負(fù)載均衡表現(xiàn)正常,排除。
2,查看單臺(tái)服務(wù)日志出現(xiàn)OOM,可以斷定是服務(wù)出問(wèn)題了。
分析原因
1,先重啟服務(wù)。
2,下載 *.hprof 日志,用MAT分析結(jié)果如下圖:
3,結(jié)果明顯指示tomcat線(xiàn)程池滿(mǎn)了,并指向了其中一個(gè)controller的外部請(qǐng)求。
4,結(jié)合代碼分析是請(qǐng)求外部HTTP連接沒(méi)有設(shè)置超時(shí)時(shí)間,導(dǎo)致大量請(qǐng)求堆積,tomcat線(xiàn)程池滿(mǎn)了,造成OOM。
解決辦法
1,HTTP請(qǐng)求使用連接池,設(shè)置超時(shí)響應(yīng)時(shí)間
2,加上監(jiān)控。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java web實(shí)現(xiàn)分頁(yè)查詢(xún)實(shí)例方法
在本篇文章里我們給大家分享了java web實(shí)現(xiàn)分頁(yè)查詢(xún)的詳細(xì)方法知識(shí)點(diǎn),有需要的朋友們參考學(xué)習(xí)下。2018-10-10Java實(shí)現(xiàn)圖片驗(yàn)證碼具體代碼
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)圖片驗(yàn)證碼具體代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10Springboot通過(guò)配置WebMvcConfig處理Cors非同源訪問(wèn)跨域問(wèn)題
這篇文章主要介紹了Springboot通過(guò)配置WebMvcConfig處理Cors非同源訪問(wèn)跨域問(wèn)題,關(guān)于Cors跨域的問(wèn)題,前端有代理和jsonp的常用方式解決這種非同源的訪問(wèn)拒絕策略2023-04-04解析分別用遞歸與循環(huán)的方式求斐波那契數(shù)列的實(shí)現(xiàn)方法
本篇文章是對(duì)分別用遞歸與循環(huán)的方式求斐波那契數(shù)列的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06SpringCloud微服務(wù)架構(gòu)實(shí)戰(zhàn)之微服務(wù)治理功能的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud微服務(wù)架構(gòu)實(shí)戰(zhàn)之微服務(wù)治理,這些治理工具主要包括服務(wù)的注冊(cè)與發(fā)現(xiàn)、負(fù)載均衡管理、動(dòng)態(tài)路由、服務(wù)降級(jí)和故障轉(zhuǎn)移、鏈路跟蹤、服務(wù)監(jiān)控等,需要的朋友可以參考下2022-02-02java類(lèi)中serialVersionUID的作用及其使用
這篇文章主要介紹了java類(lèi)中serialVersionUID的作用及其使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12解決Eclipse打開(kāi).java文件異常,提示用系統(tǒng)工具打開(kāi)的問(wèn)題
這篇文章主要介紹了解決Eclipse打開(kāi).java文件異常,提示用系統(tǒng)工具打開(kāi)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01關(guān)于springboot集成swagger及knife4j的增強(qiáng)問(wèn)題
這篇文章主要介紹了springboot集成swagger以及knife4j的增強(qiáng),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03Mybatis動(dòng)態(tài)查詢(xún)字段及表名的實(shí)現(xiàn)
本文主要介紹了Mybatis動(dòng)態(tài)查詢(xún)字段及表名的實(shí)現(xiàn),通過(guò)靈活運(yùn)用Mybatis提供的動(dòng)態(tài)SQL功能,我們可以構(gòu)建更加靈活、高效的查詢(xún)語(yǔ)句,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2024-01-01