作為Web容器,需要承受較高的訪問量,能夠同時回應不同使用者的請求,能夠在惡劣環境下保持較高的穩定性和健壯性。在HTTP伺服器領域,Apache HTTPD的效率是最高的,也是最為穩定的,但它只能處理靜態頁面的請求,如果需要支援動態頁面請求,則必須安裝相應的外掛程式,比如mod_perl可以處理Perl腳本,mod_python可以處理Python腳本。
Tomcat是使用最廣的JAVA Web容器,功能強大,可擴充性強。
Tomcat 的執行緒池位於tomcat-util.jar檔中,包含了兩種執行緒池方案。
- 方案一:使用APR的Pool技術,使用了JNI;
- 方案二:使用JAVA實現的ThreadPool。這裡介紹的是第二種。如果想瞭解APR的Pool技術,可以查看APR的原始程式碼。
ThreadPool預設創建了5個執行緒,保存在一個200維的執行緒陣列中,創建時就啟動了這些執行緒,當然在沒有請求時,它們都處理「等待」狀態(其實就是一個while迴圈,不停的等待notify)。如果有請求時,空閒執行緒會被喚醒執行使用者的請求。
具體的請求過程是: 服務啟動時,創建一個一維執行緒陣列(maxThread=200個),並創建空閒執行緒(minSpareThreads=5個)隨時等待使用者請求。 當有使用者請求時,調用 threadpool.runIt(ThreadPoolRunnable)方法,將一個需要執行的實例傳給ThreadPool中。其中使用者需要執行的實例必須實現ThreadPoolRunnable介面。 ThreadPool 首先查找空閒的執行緒,如果有則用它運行要執行ThreadPoolRunnable;如果沒有空閒執行緒並且沒有超過maxThreads,就一次性創建 minSpareThreads個空閒執行緒;如果已經超過了maxThreads了,就等待空閒執行緒了。總之,要找到空閒的執行緒,以便用它執行實例。找到後,將該執行緒從執行緒陣列中移走。 接著喚醒已經找到的空閒執行緒,用它運行執行實例(ThreadPoolRunnable)。 運行完ThreadPoolRunnable後,就將該執行緒重新放到執行緒陣列中,作為空閒執行緒供後續使用。
執行緒池作為提高程式處理資料能力的一種方案,應用非常廣泛。大量的伺服器都或多或少的使用到了執行緒池技術,不管是用JAVA還是C++實現,執行緒池都有如下的特點:
執行緒池一般有三個重要參數:
- 1. 最大執行緒數。在程式運行的任何時候,執行緒數總數都不會超過這個數。如果請求數量超過最大數時,則會等待其他執行緒結束後再處理。
- 2. 最大共用執行緒數,即最大空閒執行緒數。如果當前的空閒執行緒數超過該值,則多餘的執行緒會被殺掉。
- 3. 最小共用執行緒數,即最小空閒執行緒數。如果當前的空閒數小於該值,則一次性創建這個數量的空閒執行緒,所以它本身也是一個創建執行緒的步長。
執行緒池有兩個概念:
- 1. Worker執行緒。工作執行緒主要是運行執行代碼,有兩種狀態:空閒狀態和運行狀態。在空閒狀態時,類似「休眠」,等待任務;處理運行狀態時,表示正在運行任務(Runnable)。
- 2. 輔助執行緒。主要負責監控執行緒池的狀態:空閒執行緒是否超過最大空閒執行緒數或者小於最小空閒執行緒數等。如果不滿足要求,就調整之。
web server允許的最大執行緒連接數還受制于作業系統的內核參數設置,通常Windows是2000個左右,Linux是1000個左右。
編輯tomcat安裝目錄下的conf目錄下的server.xml檔,在tomcat設定檔server.xml中的<Connector />配置中,和連接數相關的參數有:
- maxThreads=”150″ 表示最多同時處理150個連接,Tomcat使用執行緒來處理接收的每個請求。這個值表示Tomcat可創建的最大的執行緒數。預設值200。
- minSpareThreads=”25″ 表示即使沒有人使用也開這麼多空執行緒等
- maxSpareThreads=”75″ 表示如果最多可以空75個執行緒,例如某時刻有80人訪問,之後沒有人訪問了,則tomcat不會保留80個空執行緒,而是關閉5個空的。
(一旦創建的執行緒超過這個值,Tomcat就會關閉不再需要的socket執行緒。預設值50。)
acceptCount=”100″ 當同時連接的人數達到maxThreads時,還可以接收排隊的連接數量,超過這個連接的則直接返回拒絕連接。(指定當任何能夠使用的處理請求的執行緒數都被使用時,能夠放到處理佇列中的請求數,超過這個數的請求將不予處理。預設值10。 )
其中和最大連接數相關的參數為maxThreads和acceptCount。如果要加大併發連接數,應同時加大這兩個參數。
執行緒池配置:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" keystoreFile="/Users/max/Documents/settings/tomcat.keystore" keystorePass="changeit" keyAlias="tomcat" clientAuth="false" sslProtocol="TLS" />