【尊重原創文章摘自:http://blog.csdn.net/yaerfeng/article/details/7679740】tomcat的運行模式有3種.修改他們的運行模式.3種模式的運行是否成功,可以看他的啟動控制台,或者啟動日誌.或者登錄他們的預設頁面http://localhost:808...
【尊重原創文章摘自:http://blog.csdn.net/yaerfeng/article/details/7679740】
tomcat的運行模式有3種.修改他們的運行模式.3種模式的運行是否成功,可以看他的啟動控制台,或者啟動日誌.或者登錄他們的預設頁面http://localhost:8080/查看其中的伺服器狀態。
1)bio
預設的模式,性能非常低下,沒有經過任何優化處理和支持.
2)nio
利用java的非同步io護理技術,no blocking IO技術.
想運行在該模式下,直接修改server.xml里的Connector節點,修改protocol為
<Connector port="80" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" URIEncoding="UTF-8" useBodyEncodingForURI="true" enableLookups="false" redirectPort="8443" />
啟動後,就可以生效。
3)apr
安裝起來最困難,但是從操作系統級別來解決非同步的IO問題,大幅度的提高性能.
必須要安裝apr和native,直接啟動就支持apr。下麵的修改純屬多餘,僅供大家擴充知識,但仍然需要安裝apr和native
如nio修改模式,修改protocol為org.apache.coyote.http11.Http11AprProtocol
Tomcat 6.X實現了JCP的Servlet 2.5和JSP2.1的規範,並且包括其它很多有用的功能,使它成為開發
和部署web應用和web服務的堅實平臺。
NIO (No-blocking I/O)從JDK 1.4起,NIO API作為一個基於緩衝區,並能提供非阻塞I/O操作的API
被引入。
作為開源web伺服器的java實現,tomcat幾乎就是web開發者開發、測試的首選,有很多其他商業服務
器的開發者也會優先選擇tomcat作為開發時候使用,而在部署的時候,把應用發佈在商業伺服器上。也有
許多商業應用部署在tomcat上,tomcat承載著其核心的應用。但是很多開發者很迷惑,為什麼在自己的應
用里使用tomcat作為平臺的時候,而併發用戶超過一定數量,伺服器就變的非常繁忙,而且很快就出現了
connection refuse的錯誤。但是很多商業應用部署在tomcat上運行卻安然無恙。
其中有個很大的原因就是,配置良好的tomcat都會使用APR(Apache Portable Runtime),APR是
Apache HTTP Server2.x的核心,它是高度可移植的本地庫,它使用高性能的UXIN I/O操作,低性能的
java io操作,但是APR對很多Java開發者而言可能稍稍有點難度,在很多OS平臺上,你可能需要重新編
譯APR。但是從Tomcat6.0以後, Java開發者很容易就可以是用NIO的技術來提升tomcat的併發處理能力。
但是為什麼NIO可以提升tomcat的併發處理能力呢,我們先來看一下java 傳統io與 java NIO的差別。
Java 傳統的IO操作都是阻塞式的(blocking I/O), 如果有socket的編程基礎,你會接觸過堵塞socket和
非堵塞socket,堵塞socket就是在accept、read、write等IO操作的的時候,如果沒有可用符合條件的資
源,不馬上返回,一直等待直到有資源為止。而非堵塞socket則是在執行select的時候,當沒有資源的時
候堵塞,當有符合資源的時候,返回一個信號,然後程式就可以執行accept、read、write等操作,一般來
說,如果使用堵塞socket,通常我們通常開一個線程accept socket,當讀完這次socket請求的時候,開一
個單獨的線程處理這個socket請求;如果使用非堵塞socket,通常是只有一個線程,一開始是select狀,
當有信號的時候可以通過 可以通過多路復用(Multiplexing)技術傳遞給一個指定的線程池來處理請求,然
後原來的線程繼續select狀態。 最簡單的多路復用技術可以通過java管道(Pipe)來實現。換句話說,如果
客戶端的併發請求很大的時候,我們可以使用少於客戶端併發請求的線程數來處理這些請求,而這些來不
及立即處理的請求會被阻塞在java管道或者隊列裡面,等待線程池的處理。請求 聽起來很複雜,在這個架
構當道的java 世界里,現在已經有很多優秀的NIO的架構方便開發者使用,比如Grizzly,Apache Mina等
等,如果你對如何編寫高性能的網路伺服器有興趣,你可以研讀這些源代碼。
簡單說一下,在web伺服器上阻塞IO(BIO)與NIO一個比較重要的不同是,我們使用BIO的時候往往會
為每一個web請求引入多線程,每個web請求一個單獨的線程,所以併發量一旦上去了,線程數就上去
了,CPU就忙著線程切換,所以BIO不合適高吞吐量、高可伸縮的web伺服器;而NIO則是使用單線程(單
個CPU)或者只使用少量的多線程(多CPU)來接受Socket,而由線程池來處理堵塞在pipe或者隊列里的請
求.這樣的話,只要OS可以接受TCP的連接,web伺服器就可以處理該請求。大大提高了web伺服器的可
伸縮性。
我們來看一下配置,你只需要在server.xml里把 HTTP Connector做如下更改,
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
改為
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443" />
然後啟動伺服器,你會看到org.apache.coyote.http11.Http11NioProtocol start的信息,表示NIO已經啟動。其他的配置請參考官方配置文檔。
Enjoy it.
最後貼上官方文檔上對tomcat的三種Connector的方式做一個簡單比較,
Java Blocking Connector Java Nio Blocking Connector APR Connector Classname Http11Protocol Http11NioProtocol Http11AprProtocol Tomcat Version 3.x 4.x 5.x 6.x 6.x 5.5.x 6.x Support Polling NO YES YES Polling Size N/A Unlimited - Restricted by mem Unlimited Read HTTP Request Blocking Blocking Blocking Read HTTP Body Blocking Blocking Blocking Write HTTP Response Blocking Blocking Blocking SSL Support Java SSL Java SSL OpenSSL SSL Handshake Blocking Non blocking Blocking Max Connections maxThreads See polling size See polling size
如果讀者有socket的編程基礎,應該會接觸過堵塞socket和非堵塞socket,堵塞socket就是在accept、read、write等IO操作的的時候,如果沒有可用符合條件的資源,不馬上返回,一直等待直到有資源為止。而非堵塞socket則是在執行select的時候,當沒有資源的時候堵塞,當有符合資源的時候,返回一個信號,然後程式就可以執行accept、read、write等操作,這個時候,這些操作是馬上完成,並且馬上返回。而windows的winsock則有所不同,可以綁定到一個EventHandle里,也可以綁定到一個HWND里,當有資源到達時,發出事件,這時執行的io操作也是馬上完成、馬上返回的。一般來說,如果使用堵塞socket,通常我們時開一個線程accept socket,當有socket鏈接的時候,開一個單獨的線程處理這個socket;如果使用非堵塞socket,通常是只有一個線程,一開始是select狀態,當有信號的時候馬上處理,然後繼續select狀態。 按照大多數人的說法,堵塞socket比非堵塞socket的性能要好。不過也有小部分人並不是這樣認為的,例如Indy項目(Delphi一個比較出色的網路包),它就是使用多線程+堵塞socket模式的。另外,堵塞socket比非堵塞socket容易理解,符合一般人的思維,編程相對比較容易。 nio其實也是類似上面的情況。在JDK1.4,sun公司大範圍提升Java的性能,其中NIO就是其中一項。Java的IO操作集中在java.io這個包中,是基於流的阻塞API(即BIO,Block IO)。對於大多數應用來說,這樣的API使用很方便,然而,一些對性能要求較高的應用,尤其是服務端應用,往往需要一個更為有效的方式來處理IO。從JDK 1.4起,NIO API作為一個基於緩衝區,並能提供非阻塞O操作的API(即NIO,non-blocking IO)被引入。 BIO與NIO一個比較重要的不同,是我們使用BIO的時候往往會引入多線程,每個連接一個單獨的線程;而NIO則是使用單線程或者只使用少量的多線程,每個連接共用一個線程。 這個時候,問題就出來了:我們非常多的java應用是使用ThreadLocal的,例如JSF的FaceContext、Hibernate的session管理、Struts2的Context的管理等等,幾乎所有框架都或多或少地應用ThreadLocal。如果存在衝突,那豈不驚天動地? 後來終於在Tomcat6的文檔(http://tomcat.apache.org/tomcat-6.0-doc/aio.html)找到答案。根據上面說明,應該Tomcat6應用nio只是用在處理髮送、接收信息的時候用到,也就是說,tomcat6還是傳統的多線程Servlet,我畫了下麵兩個圖來列出區別: tomcat5:客戶端連接到達 -> 傳統的SeverSocket.accept接收連接 -> 從線程池取出一個線程 -> 在該線程讀取文本並且解析HTTP協議 -> 在該線程生成ServletRequest、ServletResponse,取出請求的Servlet -> 在該線程執行這個Servlet -> 在該線程把ServletResponse的內容發送到客戶端連接 -> 關閉連接。 我以前理解的使用nio後的tomcat6:客戶端連接到達 -> nio接收連接 -> nio使用輪詢方式讀取文本並且解析HTTP協議(單線程) -> 生成ServletRequest、ServletResponse,取出請求的Servlet -> 直接在本線程執行這個Servlet -> 把ServletResponse的內容發送到客戶端連接 -> 關閉連接。 實際的tomcat6:客戶端連接到達 -> nio接收連接 -> nio使用輪詢方式讀取文本並且解析HTTP協議(單線程) -> 生成ServletRequest、ServletResponse,取出請求的Servlet -> 從線程池取出線程,併在該線程執行這個Servlet -> 把ServletResponse的內容發送到客戶端連接 -> 關閉連接。 從上圖可以看出,BIO與NIO的不同,也導致進入客戶端處理線程的時刻有所不同:tomcat5在接受連接後馬上進入客戶端線程,在客戶端線程里解析HTTP協議,而tomcat6則是解析完HTTP協議後才進入多線程,另外,tomcat6也比5早脫離客戶端線程的環境。 實際的tomcat6與我之前猜想的差別主要集中在如何處理servlet的問題上。實際上即使拋開ThreadLocal的問題,我之前理解tomcat6只使用一個線程處理的想法其實是行不同的。大家都有經驗:servlet是基於BIO的,執行期間會存在堵塞的,例如讀取文件、資料庫操作等等。tomcat6使用了nio,但不可能要求servlet裡面要使用nio,而一旦存在堵塞,效率自然會銳降。 所以,最終的結論當然是tomcat6的servlet裡面,ThreadLocal照樣可以使用,不存在衝突。