Tomcat自身的調優是針對conf/server.xml中的幾個引數的調優設定。首先是對這幾個引數的含義要有深刻而清楚的理解。以tomcat8.5為例,講解引數。
同時也得認識到一點,tomcat調優也受制於linux核心。linux核心對tcp連線也有幾個引數可以調優。
因此我們可以將tomcat調優分為linux核心最佳化、java虛擬機器調優和tomcat自身的最佳化。
一、Tomcat自身最佳化
1. maxThreads :tomcat建立的最大執行緒數,也就是同時處理的請求最大併發數。預設值是200
官網:The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. If an executor is associated with this connector, this attribute is ignored as the connector will execute tasks using the executor rather than an internal thread pool. Note that if an executor is configured any value set for this attribute will be recorded correctly but it will be reported (e.g. via JMX) as -1
to make clear that it is not used.
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的配置並沒有一個最優值,一定要根據具體情況來配置。
最好的做法是:在不斷測試的基礎上,不斷調整、最佳化,才能得到最合理的配置。
2. acceptCount:當tomcat的執行緒數達到了最大時,接收排隊的最大請求個數。預設值為100
官網:the maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 100.
maxThreads與acceptCount這兩個值是如何起作用的呢?
情況1:接受一個請求,此時tomcat起動的執行緒數沒有到達maxThreads,tomcat會起動一個執行緒來處理此請求。
情況2:接受一個請求,此時tomcat起動的執行緒數已經到達maxThreads,tomcat會把此請求放入等待佇列,等待空閒執行緒。
情況3:接受一個請求,此時tomcat起動的執行緒數已經到達maxThreads,等待佇列中的請求個數也達到了acceptCount,此時tomcat會直接拒絕此次請求,返回connection refused。
對於第3種情況,在看過一篇分析connection timeout問題產生的原因後,等待佇列的請求個數這個值可能是由acceptCount引數決定,也有可能由linux核心引數net.core.somaxconn決定。
關聯:我在網上看來一篇文章寫分析linux上TCP connection timeout的原因,這篇文章中提到一個核心引數 net.core.somaxconn。
我就想tomcat的acceptCount與net.core.somaxconn到底是什麼關係呢。
我做了一個實驗,
1. 我將tomcat的acceptCount設定為3000 ,net.core.somaxconn設定為8192
那麼我用ss -lt 指令檢視在tomcat起的埠上的send_q值是3000 可見這是acceptCount的值。
2.我將tomcat的acceptCount設定為10000,net.core.somaxconn設定為8192
同樣用ss -lt指令檢視在tomcat起的埠上的send_q值是8192,可見這是somaxconn的值。
所以,我總結的是,acceptCount設定的值要一般小於net.core.somaxconn這個引數,這樣acceptCount的值才會起作用。net.core.somaxconn 這個引數預設值是128 ,所以需要改這個引數值。後面再介紹改這個值的方法。
acceptCount如何配置?(轉)
我一般是設定的跟maxThreads一樣大,這個值應該是主要根據應用的訪問峰值與平均值來權衡配置的。
如果設的較小,可以保證接受的請求較快相應,但是超出的請求可能就直接被拒絕
如果設的較大,可能就會出現大量的請求超時的情況,因為我們系統的處理能力是一定的。
3. maxConnections
官網:
The maximum number of connections that the server will accept and process at any given time. When this number has been reached, the server will accept, but not process, one further connection. This additional connection be blocked until the number of connections being processed falls below maxConnections at which point the server will start accepting and processing new connections again. Note that once the limit has been reached, the operating system may still accept connections based on the acceptCount
setting. The default value varies by connector type. For NIO and NIO2 the default is 10000
. For APR/native, the default is 8192
.
Note that for APR/native on Windows, the configured value will be reduced to the highest multiple of 1024 that is less than or equal to maxConnections. This is done for performance reasons.
If set to a value of -1, the maxConnections feature is disabled and connections are not counted.
Tomcat允許的同時存在的最大連線數
acceptCount、maxConnections是tcp層相關的引數。
4.connectionTimeOut :connectionTimeOut=10000是說建立一個socket連線後,如果一直沒有收到客戶端的FIN,也沒有資料過來,那麼此連線也必須等到10s後,才能被超時釋放,我理解是tomcat就直接釋放這個連線。以毫秒為單位,server.xml預設設定是20秒。
官網:The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. Use a value of -1 to indicate no (i.e. infinite) timeout. The default value is 60000 (i.e. 60 seconds) but note that the standard server.xml that ships with Tomcat sets this to 20000 (i.e. 20 seconds). Unless disableUploadTimeout is set to false
, this timeout will also be used when reading the request body (if any).
修改方法:
vi server.xml 開啟server.xml檔案
將
<!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/> -->
修改為:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="1500" minSpareThreads="50" prestartminSpareThreads="true"/>
將
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
修改為
<Connector executor ="tomcatThreadPool" port="8009" protocol="org.apache.coyote.http11.Http11Nio2Protocol" connectionTimeout="20000" maxConnections="10000" redirectPort="8443" acceptCount="1500"/>
下面的圖為TCP三次握手與accept互動
SYN佇列稱為半連線佇列,由核心引數 net.ipv4.tcp_max_syn_backlog 設定.
Accept佇列稱為完全連線佇列,三次握手已經完成,但還未被應用層接收(accept),但也處於ESTABLISHED狀態。佇列長度由listen的backlog引數和核心的 net.core.somaxconn 引數共同決定。由listen()函式的第二個引數 backlog 指定,核心硬限制由 net.core.somaxconn 限制,即佇列長度實際的值由min(backlog,somaxconn) 來決定
客戶端使用connect向伺服器傳送TCP連線,三次握手就發生了。當1.1步驟 客戶端首先傳送SYN到達服務端後,核心會把連線資訊放到SYN佇列中,同時回一個SYN+ACK包給客戶端。一段時間後,客戶端再次發來ACK包後,核心會把連線從SYN佇列中取出,再把這個連線放到ACCEPT佇列中。應用伺服器呼叫accept時,其實就是直接從ACCEPT佇列中取出已經建立成功的連線套接字。
還有一張圖是TCP握手建立連線的流程和佇列
Tomcat原理概要
Tomcat大致分為兩個部分,Connector元件及Container元件。Connector元件負責控制入口連線,並關聯著一個Executor。Container負責Servlet容器的實現,Executor負責具體的業務邏輯,如Servlet的執行。一個請求到達伺服器後,經過以下關鍵幾步,參見下圖:
-
OS與客戶端握手並建立連線,並將建立的連線放入完成佇列,不妨叫Acceptor Queque。這個佇列的長度就是Connector的acceptCount值。
-
Tomcat中的acceptor執行緒,不斷從Acceptor Queque中獲取連線。
-
Acceptor Queque佇列中沒有連線,Acceptor執行緒繼續監視
-
Acceptor Queque佇列中有新連線,Acceptor執行緒將檢查當前的連線數是否超過了maxConnections
-
如果超過maxConnections,則阻塞。直到連線數小於maxConnections,acceptor執行緒將請求交由Executor負責執行。
-
Executor將分配worker執行緒來處理請求資料的讀取,處理(servlet的執行)以及響應。
acceptCount
acceptCount 實際上是Bind Socket時候傳遞的backlog值,在linux平臺下含義是已經建立連線還沒有被應用獲取的連線佇列最大長度。此時,如果請求個數達到了acceptCount,新進的請求將丟擲refuse connection.
二、Linux核心引數最佳化
1. linux系統對當前使用者的單一程序同時可開啟的檔案數量的限制
檢視系統允許當前使用者程序開啟的檔案數量的限制: ulimit -u 預設值為1024 。即是Linux作業系統對一個程序開啟的檔案控制代碼數量的限制
對於想支援更高數量的TCP併發連線的通訊處理程式,就必須修改Linux對當前使用者的程序同時開啟的檔案數量的軟限制(soft limit)和硬限制(hardlimit)。其中軟限制是指Linux在當前系統能夠承受的範圍內進一步限制使用者同時開啟的檔案數;硬限制則是根據系統硬體資源狀況(主要是系統記憶體)計算出來的系統最多可同時開啟的檔案數量。通常軟限制小於或等於硬限制。
修改方法:
sudo vi /etc/security/limits.conf
增加如下:
prouser soft nofile 65536
prouser hard nofile 65536
prouser soft nproc 65536
prouser hard nproc 65536
修改完後儲存此檔案。
nproc是作業系統級別對每個使用者建立的程序數的限制
2.Linux網路核心對TCP連線的有關限制
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 10000
net.core.somaxconn=8192 accept佇列的長度跟這個引數有關
三、JVM調優
JAVA_OPTS="$JAVA_OPTS -server -Xmn2000m -Xms4000m -Xmx4000m -XX:PermSize=128m -XX:+UseConcMarkSweepGC -XX:MaxPermSize=512m -Djuli-logback.configurationFile=file:$CATALINA_HOME/conf/logback.xml"
預設值:
<!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/> -->修改為:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" minSpareThreads="30" maxIdleTime="60000" prestartminSpareThreads = "true" maxQueueSize = "100" />引數解釋:
maxThreads:最大併發數,預設設定 200,一般建議在 500 ~ 800,根據硬體設施和業務來判斷
minSpareThreads:Tomcat 初始化時建立的執行緒數,預設設定 25
maxIdleTime:如果當前執行緒大於初始化執行緒,那空閒執行緒存活的時間,單位毫秒,預設60000=60秒=1分鐘。
prestartminSpareThreads:在 Tomcat 初始化的時候就初始化 minSpareThreads 的引數值,如果不等於 true,minSpareThreads 的值就沒啥效果了
maxQueueSize:最大的等待佇列數,超過則拒絕請求
轉自
Tomcat調優總結(Tomcat自身最佳化、Linux核心最佳化、JVM最佳化) - hxwang - 部落格園
https://www.cnblogs.com/whx7762/p/9290242.html