Tomcat自身的調優是針對conf/server.xml中的幾個參數的調優設置。首先是對這幾個參數的含義要有深入而清楚的理解。以tomcat8.5爲例,講解參數。html
同時也得認識到一點,tomcat調優也受制於linux內核。linux內核對tcp鏈接也有幾個參數能夠調優。java
所以咱們能夠將tomcat調優分爲linux內核優化、java虛擬機調優和tomcat自身的優化。linux
官網: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如何配置(轉)apache
通常的服務器操做都包括量方面:1計算(主要消耗cpu),2等待(io、數據庫等)tomcat
第一種極端狀況,若是咱們的操做是純粹的計算,那麼系統響應時間的主要限制就是cpu的運算能力,此時maxThreads應該儘可能設的小,下降同一時間內爭搶cpu的線程個數,能夠提升計算效率,提升系統的總體處理能力。服務器
第二種極端狀況,若是咱們的操做純粹是IO或者數據庫,那麼響應時間的主要限制就變爲等待外部資源,此時maxThreads應該儘可能設的大,這樣才能提升同時處理請求的個數,從而提升系統總體的處理能力。此狀況下由於tomcat同時處理的請求量會比較大,因此須要關注一下tomcat的虛擬機內存設置和linux的open file限制。網絡
我在測試時遇到一個問題,maxThreads我設置的比較大好比3000,當服務的線程數大到必定程度時,通常是2000出頭,單次請求的響應時間就會急劇的增長,多線程
百思不得其解這是爲何,四處尋求答案無果,最後我總結的緣由多是cpu在線程切換時消耗的時間隨着線程數量的增長愈來愈大,併發
cpu把大多數時間都用來在這2000多個線程直接切換上了,固然cpu就沒有時間來處理咱們的程序了。
之前一直簡單的認爲多線程=高效率。。其實多線程自己並不能提升cpu效率,線程過多反而會下降cpu效率。
當cpu核心數<線程數時,cpu就須要在多個線程直接來回切換,以保證每一個線程都會得到cpu時間,即一般咱們說的併發執行。
因此maxThreads的配置絕對不是越大越好。
現實應用中,咱們的操做都會包含以上兩種類型(計算、等待),因此maxThreads的配置並無一個最優值,必定要根據具體狀況來配置。
最好的作法是:在不斷測試的基礎上,不斷調整、優化,才能獲得最合理的配置。
官網: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同樣大,這個值應該是主要根據應用的訪問峯值與平均值來權衡配置的。
若是設的較小,能夠保證接受的請求較快相應,可是超出的請求可能就直接被拒絕
若是設的較大,可能就會出現大量的請求超時的狀況,由於咱們系統的處理能力是必定的。
官網:
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.
查看系統容許當前用戶進程打開的文件數量的限制: 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是操做系統級別對每一個用戶建立的進程數的限制
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隊列的長度跟這個參數有關
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:最大的等待隊列數,超過則拒絕請求