在上周三下午時,客戶、業務和測試人員同時反潰生產環境登錄進入不了系統,我親自測試時,第一次登錄進去了,待退出后再登錄時,復現了客戶的問題,場景像是請求連接被拒絕了,分析后判斷是spring boot的連接數使用完了,於是重啟了服務,客戶訪問都恢復正常。雖然問題暫時解決了,但實質原因還無法確定。根據分析,判斷是spring boot服務連接被拒絕,查看配置的最大連接數和最大線程數時,配置為:
#最大連接數
server.tomcat.max-connections=300
#最大線程數
server.tomcat.max-threads=200
為了驗證自己的分析,於是將最大連接數和最大線程數都設置為3,如下:
#最大連接數
server.tomcat.max-connections=3
#最大線程數
server.tomcat.max-threads=3
啟動服務后,打開4個瀏覽器(IE、google、火狐、360),在這4個瀏覽器中,登錄IE、google和火狐后,再登錄360瀏覽器時,生產環境的場景復現了;重啟服務,再先登錄360、火狐、IE后,再登錄google時,生產環境的場景同樣復現了。
由此斷定,spring boot中內嵌的tomcat的最大連接數達到最大值后,在沒有連接數釋放的情況下,新的請求會被服務器拒絕,即測試驗證中第4個瀏覽器進入不了系統的原因。
由於公司該企業級服務系統的上線,用戶量遠少於300,就很奇怪連接數為何會被耗盡。
經過進一步排查,是由於系統上線后,用戶的登錄,支持多個用戶共用一個賬號,同時單個用戶的會話有效期設置為了3天,客戶之前在系統中出現過瀏覽器兼容性問題導致一個客戶在一台電腦的多個瀏覽器上登錄,另外業務人員、測試人員都在上面驗證着客戶的問題,都在占用着連接數,綜合以上因素,導致了該系統上300個連接數被耗盡了。
為了解決這個問題,必須對tomcat的最大連接數等參數做優化設置。查詢了tomcat的常用參數,其中最大連接數、最大線程數和最大等待數信息如下 :
1)maxThreads(最大線程數)
每一次HTTP請求到達Web服務器,Web服務器都會創建一個線程來處理該請求,該參數決定了應用服務同時可以處理多少個HTTP請求,tomcat默認為200;
2)accepCount(最大等待數)
當調用Web服務的HTTP請求數達到tomcat的最大線程數時,還有新的HTTP請求到來,這時tomcat會將該請求放在等待隊列中,這個acceptCount就是指能夠接受的最大等待數,默認100.如果等待隊列也被放滿了,這個時候再來新的請求就會被tomcat拒絕(connection refused);
3)maxConnections(最大連接數)
這個參數是指在同一時間,tomcat能夠接受的最大連接數。一般這個值要大於maxThreads+acceptCount。
根據公司用戶量及機器配置信息,公司的最大連接數、最大線程數和最大等待數優化為:
#最大連接數
server.tomcat.max-connections=2000
#最大線程數
server.tomcat.max-threads=1000
#最大等待數
server.tomcat.accept-count=800
1)maxThreads(最大線程數)
每一次HTTP請求到達Web服務器,Web服務器都會創建一個線程來處理該請求,該參數決定了應用服務同時可以處理多少個HTTP請求,tomcat默認為200;
2)accepCount(最大等待數)
當調用Web服務的HTTP請求數達到tomcat的最大線程數時,還有新的HTTP請求到來,這時tomcat會將該請求放在等待隊列中,這個acceptCount就是指能夠接受的最大等待數,默認100.如果等待隊列也被放滿了,這個時候再來新的請求就會被tomcat拒絕(connection refused);
3)maxConnections(最大連接數)
這個參數是指在同一時間,tomcat能夠接受的最大連接數。一般這個值要大於maxThreads+acceptCount。
根據公司用戶量及機器配置信息,公司的最大連接數、最大線程數和最大等待數優化為:
#最大連接數
server.tomcat.max-connections=2000
#最大線程數
server.tomcat.max-threads=1000
#最大等待數
server.tomcat.accept-count=800
增加線程是有成本的。JVM中默認情況下在創建新線程時會分配固定大小的線程棧,所以更多的線程異味着更多的內存;
更多的線程會帶來更多的線程上下文切換成本。
如果線程占用的資源過大,會導致內存溢出(Cannt’ allocate memory)情況出現。因此需要對JVM及線程的相關參數做合理配置。
在jvm內存調整過程中,我們經常使用的參數就是:
-Xms 為jvm啟動時分配的初始堆的大小,也是堆大小的最小值,比如-Xms200m,表示分配200M
-Xmx 為jvm運行過程中分配的最大堆內存,比如-Xmx500m,表示jvm進程最多只能夠占用500M內存
-Xss 為jvm啟動的每個線程分配的內存大小,默認JDK1.4中是256K,JDK1.5+中是1M