1. 程式人生 > >tomcat 的最大連接數

tomcat 的最大連接數

兩種 check 最優 || state 最大值 rac sed 含義

前提說明
為了確保服務不會被過多的http長連接壓垮,我們需要對tomcat設定個最大連接數,超過這個連接數的請求會拒絕,讓其負載到其它機器。達到保護自己的同時起到連接數負載均衡的作用。

動手去做
一開始根據故障todoList提供的參數MaxKeepAliveRequests,進行驗證,我們將tomcat配置server.xml修改為:

同時,啟動客戶端模擬30個長連接。

預期應該只有10個連接能保持住。
結果與預期不符,30個連接都連上了,而且正常。
這由此懷疑提供的配置參數是否是真正限制最大連接數的含義了。

KeepAlive是在HTTP1.1中定義的,用來保持客戶機和服務器的長連接,通過減少建立TCP Session的次數來提高性能。常用的配置參數有{KeepAlive, KeepAliveTimeout, MaxKeepAliveRequests}。逐個說來:

KeepAlive是決定開啟KeepAlive支持;
KeepAliveTimeout決定一 個KeepAlive的連接能保持多少時間,Timeout就盡快shutdown鏈接,若還有數據必須再建立新的連接 了;
MaxKeepAliveRequests於KeepAliveTimeout相似,意思是服務多少個請求就shutdown連接。

顯然與我們想到的要求不符,再搜索其它配置參數:

maxConnections
根據字面意思覺得就應該是這個了。
去驗證吧,
!
最大連接數為10,我們啟動30個長連接,
預期應該是只有10個長連接,實際結果卻是遠超過10個。這個有點不應該啊。

實驗驗證
原來還有個參數可以覺得連接數的大小


maxThreads:tomcat起動的最大線程數,即同時處理的任務個數,默認值為200
acceptCount:當tomcat起動的線程數達到最大時,接受排隊的請求個數,默認值為100

這兩個值如何起作用,請看下面三種情況
情況1:接受一個請求,此時tomcat起動的線程數沒有到達maxThreads,tomcat會起動一個線程來處理此請求。
情況2:接受一個請求,此時tomcat起動的線程數已經到達maxThreads,tomcat會把此請求放入等待隊列,等待空閑線程。
情況3:接受一個請求,此時tomcat起動的線程數已經到達maxThreads,等待隊列中的請求個數也達到了acceptCount,此時tomcat會直接拒絕此次請求,返回connection refused

同時加上maxConnections


原來tomcat最大連接數取決於maxConnections這個值加上acceptCount這個值,在連接數達到了maxConenctions之後,tomcat仍會保持住連接,但是不處理,等待其它請求處理完畢之後才會處理這個請求。

源碼分析
tomcat的最大連接數參數是maxConnections,這個值表示最多可以有多少個socket連接到tomcat上。BIO模式下默認最大連接數是它的最大線程數(缺省是200),NIO模式下默認是10000,APR模式則是8192(windows上則是低於或等於maxConnections的1024的倍數)。如果設置為-1則表示不限制。

在tomcat裏通過一個計數器來控制最大連接,比如在Endpoint的Acceptor裏大致邏輯如下:

while (running) {
...
//if we have reached max connections, wait
countUpOrAwaitConnection(); //計數+1,達到最大值則等待

...
// Accept the next incoming connection from the server socket
socket = serverSock.accept();

...
processSocket(socket);

...
countDownConnection(); //計數-1
closeSocket(socket);
}
計數器是通過LimitLatch鎖來實現的,它內部主要通過一個java.util.concurrent.locks.AbstractQueuedSynchronizer的實現來控制。

我們將最大連接數設置為10,同時啟動超過30個長連接,
然後通過jstack可以看到acceptor線程阻塞在countUpOrAwaitConnection方法上:

http-nio-8080-Acceptor-0" daemon prio=10 tid=0x00007f9cfc191000 nid=0x1e07 waiting on condition [0x00007f9ca9fde000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076595b688> (a org.apache.tomcat.util.threads.LimitLatch$Sync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:969)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1281)
at org.apache.tomcat.util.threads.LimitLatch.countUpOrAwait(LimitLatch.java:115)
at org.apache.tomcat.util.net.AbstractEndpoint.countUpOrAwaitConnection(AbstractEndpoint.java:755)
at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:787)
at java.lang.Thread.run(Thread.java:662)
代碼層面也解釋了這種現象。

總結
tomcat能支持最大連接數由maxConnections加上acceptCount來決定。同時maxThreads如何設定?

以下部分結論引用自:http://duanfei.iteye.com/blog/1894387
一般的服務器操作都包括兩方面:1計算(主要消耗cpu),2等待(io、數據庫等)

第一種極端情況,如果我們的操作是純粹的計算,那麽系統響應時間的主要限制就是cpu的運算能力,此時maxThreads應該盡量設的小,降低同一時間內爭搶cpu的線程個數,可以提高計算效率,提高系統的整體處理能力。

第二種極端情況,如果我們的操作純粹是IO或者數據庫,那麽響應時間的主要限制就變為等待外部資源,此時maxThreads應該盡量設的大,這樣 才能提高同時處理請求的個數,從而提高系統整體的處理能力。此情況下因為tomcat同時處理的請求量會比較大,所以需要關註一下tomcat的虛擬機內 存設置和linux的open file限制。

現實應用中,我們的操作都會包含以上兩種類型(計算、等待),所以maxThreads的配置並沒有一個最優值,一定要根據具體情況來配置。

最好的做法是:在不斷測試的基礎上,不斷調整、優化,才能得到最合理的配置。

acceptCount的配置,我一般是設置的跟maxThreads一樣大,這個值應該是主要根據應用的訪問峰值與平均值來權衡配置的。

如果設的較小,可以保證接受的請求較快相應,但是超出的請求可能就直接被拒絕

如果設的較大,可能就會出現大量的請求超時的情況,因為我們系統的處理能力是一定的

Linux查看連接數,並發數
軟連接
Bat代碼
ln -s /home/ictfmcg/data/photo /var/jtnd/data/photo
tomcat 6的Connector配置如下
Xml代碼
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="800" acceptCount="1000"/>
其中最後兩個參數意義如下:
maxThreads:tomcat起動的最大線程數,即同時處理的任務個數,默認值為200
acceptCount:當tomcat起動的線程數達到最大時,接受排隊的請求個數,默認值為100
這兩個值如何起作用,請看下面三種情況
情況1:接受一個請求,此時tomcat起動的線程數沒有到達maxThreads,tomcat會起動一個線程來處理此請求。
情況2:接受一個請求,此時tomcat起動的線程數已經到達maxThreads,tomcat會把此請求放入等待隊列,等待空閑線程。
情況3:接受一個請求,此時tomcat起動的線程數已經到達maxThreads,等待隊列中的請求個數也達到了acceptCount,此時tomcat會直接拒絕此次請求,返回connection refused
maxThreads如何配置
一般的服務器操作都包括量方面:1計算(主要消耗cpu),2等待(io、數據庫等)
第一種極端情況,如果我們的操作是純粹的計算,那麽系統響應時間的主要限制就是cpu的運算能力,此時maxThreads應該盡量設的小,降低同一時間內爭搶cpu的線程個數,可以提高計算效率,提高系統的整體處理能力。
第二種極端情況,如果我們的操作純粹是IO或者數據庫,那麽響應時間的主要限制就變為等待外部資源,此時maxThreads應該盡量設的大,這樣才能提高同時處理請求的個數,從而提高系統整體的處理能力。此情況下因為tomcat同時處理的請求量會比較大,所以需要關註一下tomcat的虛擬機內存設置和linux的open file限制。
我在測試時遇到一個問題,maxThreads我設置的比較大比如3000,當服務的線程數大到一定程度時,一般是2000出頭,單次請求的響應時間就會急劇的增加,
百思不得其解這是為什麽,四處尋求答案無果,最後我總結的原因可能是cpu在線程切換時消耗的時間隨著線程數量的增加越來越大,
cpu把大多數時間都用來在這2000多個線程直接切換上了,當然cpu就沒有時間來處理我們的程序了。
以前一直簡單的認為多線程=高效率。。其實多線程本身並不能提高cpu效率,線程過多反而會降低cpu效率。
當cpu核心數<線程數時,cpu就需要在多個線程直接來回切換,以保證每個線程都會獲得cpu時間,即通常我們說的並發執行。
所以maxThreads的配置絕對不是越大越好。
現實應用中,我們的操作都會包含以上兩種類型(計算、等待),所以maxThreads的配置並沒有一個最優值,一定要根據具體情況來配置。
最好的做法是:在不斷測試的基礎上,不斷調整、優化,才能得到最合理的配置。
acceptCount的配置,我一般是設置的跟maxThreads一樣大,這個值應該是主要根據應用的訪問峰值與平均值來權衡配置的。
如果設的較小,可以保證接受的請求較快相應,但是超出的請求可能就直接被拒絕
如果設的較大,可能就會出現大量的請求超時的情況,因為我們系統的處理能力是一定的。
1、查看apache當前並發訪問數:
Bat代碼
netstat -an | grep ESTABLISHED | wc -l
對比httpd.conf中MaxClients的數字差距多少。
2、查看有多少個進程數:
Bat代碼
ps aux|grep httpd|wc -l
3、可以使用如下參數查看數據
Bat代碼
#ps -ef|grep httpd|wc -l
 1388
  統計httpd進程數,連個請求會啟動一個進程,使用於Apache服務器。
  表示Apache能夠處理1388個並發請求,這個值Apache可根據負載情況自動調整。
Bat代碼
#netstat -nat|grep -i "80"|wc -l
  4341
  netstat -an會打印系統當前網絡鏈接狀態,而grep -i "80"是用來提取與80端口有關的連接的,wc -l進行連接數統計。 www.2cto.com
  最終返回的數字就是當前所有80端口的請求總數。
Bat代碼
#netstat -na|grep ESTABLISHED|wc -l
  376
  netstat -an會打印系統當前網絡鏈接狀態,而grep ESTABLISHED 提取出已建立連接的信息。 然後wc -l統計。
  最終返回的數字就是當前所有80端口的已建立連接的總數。
Bat代碼
netstat -nat||grep ESTABLISHED|wc
- 可查看所有建立連接的詳細記錄
  查看Apache的並發請求數及其TCP連接狀態:
  Linux命令:
Bat代碼
netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}‘
  返回結果示例:
  LAST_ACK 5
  SYN_RECV 30
  ESTABLISHED 1597
  FIN_WAIT1 51
  FIN_WAIT2 504
  TIME_WAIT 1057
  其中的
  SYN_RECV表示正在等待處理的請求數;
  ESTABLISHED表示正常數據傳輸狀態;
  TIME_WAIT表示處理完畢,等待超時結束的請求數。


摘自:https://blog.csdn.net/quliuwuyiz/article/details/79979031

tomcat 的最大連接數