tomcat 最大並發數


只針對BIO模式,目標請求會sleep兩秒再返回結果,通過jmeter測試工具進行並發測試

操作系統:windows && linux

tomcat7測試:

<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000" maxThreads="1" acceptCount="2" 
redirectPort="8443" />

文檔:http://localhost:8080/docs/config/http.html

官方解釋:acceptCount對暫時無法執行的請求進行隊列保存,超出設置則拒絕連接。

測試發現無法限制住最大並發數,所有請求都可以依次執行,每次有1個線程執行(maxThreads=1)

最大並發數如果過大,大於acceptCount值好幾倍,會隨機出現連接被拒絕。

進一步調查-----------------------------------------------------------------------------------------------------------------------------------

首先關於tcp queue簡單介紹:

tcp三次握手:

第一次,客戶端發送syn,等待服務端確認,此時客戶端進入SYN_SEND狀態

第二次,服務端接收syn包並確認,發送syn+ack給客戶端,此時服務端進入SYN_RECV狀態

第三次,客戶端收到syn+ack,再次向服務端發送ack,此時客戶端進入ESTAB狀態(注意,此時服務端未必進入ESTAB狀態

 

半連接隊列:服務端維護的與客戶端保持SYN_RECV狀態的連接隊列,等待客戶端回復,當收到客戶端ack后,如果條件允許(全連接隊列未達到最大值),服務端進入ESTAB狀態,從半連接隊列移到全連接隊列的隊尾。

全連接隊列:完成三次握手等待accept。完成三次握手即進入了全連接隊列的隊尾,當進程調用accept時,全連接隊列中的隊頭項將返回給進程,並從隊列中移出連接。如果該隊列為空,那么進程將被投入睡眠,直到TCP在該隊列中放入一項才喚醒它。

在listen(int sockfd, int backlog)中,backlog在Linux 2.2之后表示的是已完成三次握手但還未被應用程序accept的隊列長度。

 

全連接隊列滿,半連接隊列未滿:

客戶端發出syn分節,服務端收下,並向客戶端發出syn+ack。

客戶端收到服務端syn+ack后,成為ESTAB狀態,向服務端發送第三次握手ack。

服務端收到ack后,發現全連接隊列已滿,默認情況下,服務端什么也不做,狀態依然是SYN_RECV。

客戶端會重傳syn和ack,當達到一定的閾值(/proc/sys/net/ipv4/tcp_synack_retries)時,客戶端與服務端斷開連接,服務端刪除客戶端在半連接隊列中的syn分節。

全連接、半連接隊列都滿:

客戶端發出syn分節,服務端發現半連接隊列已滿,直接丟棄syn,使客戶端重傳syn。

客戶端重傳syn,再次到達服務端后,服務端發現已經重傳過,則收下,並告訴客戶端syn+ack。

后續流程與上述一致,相比之下,多了一次客戶端重傳syn分節。

修改tcp參數配置:

tcp_synack_retries和tcp_syn_retries定義SYN 的重試連接次數

/etc/rc.d/rc.local文件中追加:

sysctl -w net.ipv4.tcp_synack_retries=3

sysctl -w net.ipv4.tcp_syn_retries=3

重啟。

也可直接執行命令:

sysctl -w net.ipv4.tcp_synack_retries=1

sysctl -w net.ipv4.tcp_syn_retries=3

關於隊列的長度:

半連接隊列:≈2 * min(backlog, net.ipv4.tcpmax_syn_backlog) 

全連接隊列:min(/proc/sys/net/core/somaxconn(本系統128), backlog),表示最多有 min() + 1個 ESTAB 的連接等待 accept()。

修改somaxconn,

在/etc/sysctl.conf中添加如下:

net.core.somaxconn = 2048

然后在終端中執行

sysctl -p

進一步試驗-------------------------------------------------------------------------------------------------------------------------------------------------------------------

在linux下,通過ss -ant進行觀察tcp queue

並發5個請求

 

acceptCount配置作為socket中的backlog的值,如果acceptCount不設置或者設置為0,則會取默認值,經測試是100。

全連接隊列大小為 min(/proc/sys/net/core/somaxconn(本系統128), 2) + 1=3,即等待服務端accept的ESTAB狀態的連接最多有3個,如Recv-Q所示。

3個Recv-Q為323(表示請求bytes數值)的ESTAB狀態的連接正等待server accept

1個Recv-Q為0的ESTAB狀態的連接表示server端已經accept了請求,只是還沒有返回結果(sleep中)。

1個SYN-RECV狀態是半連接狀態,位於半連接隊列當中(此時客戶端已經處於ESTAB狀態),全連接隊列已經滿了。

對於處在半連接狀態的連接,客戶端會定時重發,直至達到閾值,如下:

第一次握手

 第二次握手

 第三次握手

 客戶端發送數據包

但由於此時服務端未能將連接從半連接隊列移至全連接隊列,狀態依然是SYN-RECV,即未得到服務端ack,因此客戶端繼續發數據包

發送幾次之后,服務端有了回應,告訴客戶端說,你之前發的包丟了

然后客戶端也告訴服務端,丟失的狀態、對應的id號及次數,這里的43就是第三次握手的43,失敗次數是1

然后客戶端又開始重傳了

終於服務端受不了了,此時客戶端服務端徹底斷開。

通過調整ipv4.tcp_synack_retries和ipv4.tcp_syn_retries,可以增加重試次數

 

結論:

對於tomcat中的acceptCount只是全連接隊列的大小,就是說客戶端和服務端都已經是ESTAB狀態的連接,不考慮connectionTime的情況,在此隊列中的連接最終都會被處理。對於大於acceptCount的連接請求,如果在tcp重試閾值范圍之內完成半連接到全連接的狀態轉換,那么還是有機會被服務端accept並處理的。

因此,不能說只要大於acceptCount的連接就一定被拒絕!

 

 

參考文獻:

http://www.cnblogs.com/leezhxing/p/5329786.html

http://blog.chinaunix.net/uid-24782829-id-3456109.html

http://www.cnblogs.com/menghuanbiao/p/5212131.html

http://www.cnblogs.com/zengkefu/p/5606696.html 有詳細的源碼分析


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM