您好,登錄后才能下訂單哦!
本篇內容介紹了“如何理解Tomcat高并發之連接池、線程池”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
1
Tomcat處理用戶請求的入口組件叫做Connector,其有兩個主要的實現:BIO(blocking io)和NIO(non-blocking io)。
簡單講,BIO的實現就是對上面多線程版本的一個改進,主要點在于把“每來一個連接啟動一個線程處理”改成“每來一個連接都提交給線程池處理”。雖然線程池根據不同的配置,其工作行為會有所不同,但一般來講,使用線程池的原則是:只需創建少量的線程就可以完成大量任務的執行,由于同時至多只有固定量的線程執行,剩余的任務會被放進queue里面緩沖起來,從這個角度看,這是一個典型的生產者-消費者模型。回到tomcat BIO,acceptor不斷的接收連接,然后提交給線程池執行,acceptor就是生產者;線程池的每一個線程就是消費者,負責處理請求。
由于socket連接是長連接,連接的創建銷毀也是很耗資源的,于是http協議增加了一個keep-alive header,這個header的意思是提示服務器端,在返回http response之后,不要斷開socket,繼續處理后續http請求,這樣做的目的就是為了提高資源的可重用性。那么,對于tomcat BIO的實現,在keep-alive場景下,會有什么問題呢?如果一個線程處理的socket需要保持keep-alive,其在執行完一個http請求之后,需要阻塞在那里以等待下一個http請求,不能馬上結束(直到timeout);在某些情況下,這樣就可能存在大量的阻塞線程,新的連接不能被處理。
基于此,NIO就可以解決這個問題。NIO和BIO在請求處理部分的實現是一致的,都是基于線程池;不同的地方是:NIO的acceptor基于jdk nio實現,在收到一個連接之后,會把socketChannel注冊到poller的selector上面,當socketChannel有數據可讀時,poller就把此連接提交給線程池處理。回到上面keep-alive的場景,當一個線程處理完一個http請求之后,就可以馬上結束,當前連接則回到selector繼續監聽接下來的http請求。所以,基于NIO的執行線程就不會出現基于BIO的阻塞情況。
NIO的核心在于selector,selector可以識別到已經ready的連接和沒有ready的連接;在之前的一篇多線程文章(對比Java和.NET多線程編程)里面提到過,jdk的concurrency API有一個CompletionService類,就有點類似于nio的原理。
由于NIO天生的優勢,tomcat從8.0版本開始就把NIO設成默認的Connector,而從8.5版本開始直接就把BIO去掉了。
2
在tomcat的官網有下面一段關于如何高并發處理請求的描述:
Each incoming request requires a thread for the duration of that request. If more simultaneous requests are received than can be handled by the currently available request processing threads, additional threads will be created up to the configured maximum (the value of the maxThreads attribute). If still more simultaneous requests are received, they are stacked up inside the server socket created by the Connector, up to the configured maximum (the value of the acceptCount attribute). Any further simultaneous requests will receive "connection refused" errors, until resources are available to process them.
- https://tomcat.apache.org/tomcat-7.0-doc/config/http.html
個人覺得其沒有反映出maxConnections這個參數的作用,所以應該是:如果maxConnections小于maxThreads,最大創建的線程數就是maxConnections的值,最大連接數也是maxConnections的值;但是如果maxConnections大于maxThreads,最大創建的線程數就是maxThreads的值,最大連接數則是maxConnections的值。
由于BIO和NIO底層實現的區別,配置maxConnections的值也需要區別考慮,這在maxConnections的默認值中就有所體現(對于BIO,maxConnections的默認值是maxThreads的值;而對于NIO,maxConnections的默認值則是10000):
3
上面有提到,tomcat接收處理請求的過程其實就是一個生產者-消費者模型,影響tomcat高并發的配置也可以首先分別從這兩個方面考慮:
生產者
消費者
Queue
4
小結一下:
線程池的本質就是節省了不斷創建銷毀線程的開銷;加上queue的使用,增加了一層緩沖,一定程度緩解了計算機的壓力。當然線程池的配置,需要根據要處理的任務(CPU密集型還是io密集型)來仔細的考慮。
Tomcat里面BIO和NIO的最大區別在于讀取下一個請求時是否需要阻塞,這對于keep-alive的場景尤其重要,NIO可以大大提高吞吐量。
基于queue的生成者-消費者模型,也常常應用在系統架構層面,以緩沖生產者和消費者之間處理速度的gap,比如秒殺系統。
“如何理解Tomcat高并發之連接池、線程池”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。