SpringBoot監控Tomcat活動線程數來判斷是否完成請求處理方式
SpringBoot監控Tomcat活動線程數來判斷是否完成請求處理
最近項目中有一個需求,需要判斷應用的請求是否已經處理完畢,想瞭一下,打算通過定時任務定時監控Tomcat的活動線程數來實現。
編碼實現
新建一個SpringBoot工程,添加定時任務定時監控,代碼如下:
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); } }
測試
新建一個測試請求類,代碼如下:
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"; } }
啟動項目:
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]
訪問測試接口,觀察Tomcat線程池變化:
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]
可以看到,當有請求處理時,Tomcat的活動線程數不為0,處理完成以後回歸到0,所以可以通過活動線程數判斷當前Tomcat是否有請求還在處理,當然,應用到實際業務中,還有需要完善的地方。
Tomcat線程數占滿而導致的線上事故
事故表現形式
昨天下午4點多的時候,有同學反映說,某個服務響應時間過長,懷疑是負載均衡的問題。
排查過程
1,查看阿裡雲負載均衡表現正常,排除。
2,查看單臺服務日志出現OOM,可以斷定是服務出問題瞭。
分析原因
1,先重啟服務。
2,下載 *.hprof 日志,用MAT分析結果如下圖:
3,結果明顯指示tomcat線程池滿瞭,並指向瞭其中一個controller的外部請求。
4,結合代碼分析是請求外部HTTP連接沒有設置超時時間,導致大量請求堆積,tomcat線程池滿瞭,造成OOM。
解決辦法
1,HTTP請求使用連接池,設置超時響應時間
2,加上監控。
總結
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 用IDEA創建SpringBoot項目的詳細步驟記錄
- Spring mvc是如何實現與數據庫的前後端的連接操作的?
- Springboot如何獲取配置文件application.yml中自定義的變量並使用
- SpringBoot中ApplicationEvent和ApplicationListener用法小結
- springboot @Async 註解如何實現方法異步