Oracle的最大併發數由PROCESSES和SESSIONS決定,歸根結底由操作系統和硬件配置決定。
根據對Tomcat、Druid、Oracle三者的與併發相關的參數進行了解,結合經驗和網上的部分說法後,得出如下數據:
- Tomcat的單機併發最大線程數爲500到700。
- Druid數據庫連接池的推薦配置最大併發數(maxActive)爲20.
- Oralce的最大進程數(PROCESSES)爲300,最大SESSIONS爲300 * 1.5 + 22 = 477 (這個公式對應Oracle 11g版本)
- Nginx在windows上的最大併發數爲1024,在linux爲8192.(受限於文件系統的最大文件打開數)。
基於以上數據,進行推測:
數據庫最大併發 = 300
數據庫可以支持的連接池個數 = 477 / 20 = 23
23個連接池對應23個Tomcat,可以支撐的線程數:
23 * 500 = 11500個線程
也就是,數據庫按照PROCESSES=300的配置來的話,可以壓榨的極限是11500併發。這裏補充一點,對於Spring框架的Web應用來說,Spring會用一個線程來處理一次用戶請求(注意是一次請求,不是一次會話),處理完一次請求後,線程即回到等待狀態,等待下一次請求調用。
所以11500個併發並不代變11500個用戶,具體要看實際場景中一個用戶的單位時間訪問量。
下面來驗證以上推測。
環境準備:
-
服務器:
-
4核8G5M帶寬阿里雲服務器 * 3
-
4核4G5M帶寬阿里雲服務器 * 2
-
-
測試客戶端:
- 4核8G筆記本
-
Tomcat線程池配置
- maxThreads=500
- accept=400
- maxConnection=800
5個服務器上分散部署了共13個Tomcat和1個Nginx
首先,按照7500線程在70秒內全部發起請求,得到的結果是:前面十秒左右一切正常,10秒過後nginx開始大量請求無法響應(failed to response),原因是nginx所在的windows服務器限制了最大文件打開數量爲1024,也就是限制了nginx的併發數爲1024.
馬上把nginx轉移到linux上,其他不變。
此時,按照7500線程70秒內發起的結果如下:
線程數 | 時間 | 發出請求 | 平均響應 | 95%響應 | 錯誤率 | 吞吐量 | 數據庫平均cpu% | 數據庫峯值cpu% |
---|---|---|---|---|---|---|---|---|
3750*2 | 54s | 7499 | 12721ms | 60147ms | 15.12% | 40.8/s | 60% | 100% |
3750*2 | 54s | 7498 | 13753ms | 60358ms | 13.27% | 61.8/s | 66% | 100% |
5750*2 | 83s | 11490 | 15669ms | 60384ms | 15.97% | 56.4/s | 76% | 100% |
5750*2 | 83s | 11489 | 19229ms | 60376ms | 31.3% | 78.4/s | 50% | 100% |
5750*2 | 83s | 11489 | 19037ms | 60313ms | 36.3% | 67.56/s | 60% | 100% |
說明:線程數乘2的原因是測試腳本包含兩個請求,分別是登錄請求和加載閱卷頁面的請求。
根據壓測過程中的監控,錯誤率裏面85%來自登錄請求的連接超時錯誤。正常情況下,這個系統的登錄請求耗時1到1.5秒左右,併發場景下更嚴重。
由於這次部署的Tomcat實例數是13個,每個Tomcat的最大線程數是500,最大同時active的線程數就是7500,離預估的數據庫最大承受值11500還差一點。湊齊20多個Tomcat的工作量太大,就不繼續壓榨Oracle了。基於已有的測試結果,基本可以驗證上面的推測。