Tomcat是什麼?
Tomcat 伺服器Apache軟體基金會專案中的一個核心專案,是一個免費的開放原始碼的Web 應用伺服器,屬於輕量級應用伺服器,在中小型系統和併發訪問使用者不是很多的場合下被普遍使用,是開發和除錯JSP 程式的首選。
Tomcat的預設埠是多少,怎麼修改找到Tomcat目錄下的conf資料夾進入conf資料夾裡面找到server.xml檔案開啟server.xml檔案在server.xml檔案裡面找到下列資訊把Connector標籤的8080埠改成你想要的埠<Service name="Catalina"><Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
tomcat 有哪幾種Connector 執行模式(優化)?下面,我們先大致了解Tomcat Connector的三種執行模式。
BIO:同步並阻塞 一個執行緒處理一個請求。缺點:併發量高時,執行緒數較多,浪費資源。Tomcat7或以下,在Linux系統中預設使用這種方式。配製項:protocol=”HTTP/1.1”
NIO:同步非阻塞IO利用Java的非同步IO處理,可以通過少量的執行緒處理大量的請求,可以複用同一個執行緒處理多個connection(多路複用)。
Tomcat8在Linux系統中預設使用這種方式。
Tomcat7必須修改Connector配置來啟動。
配製項:protocol=”org.apache.coyote.http11.Http11NioProtocol”
備註:我們常用的Jetty,Mina,ZooKeeper等都是基於java nio實現.
APR:即Apache Portable Runtime,從作業系統層面解決io阻塞問題。**AIO方式,**非同步非阻塞IO(Java NIO2又叫AIO) 主要與NIO的區別主要是作業系統的底層區別.可以做個比喻:比作快遞,NIO就是網購後要自己到官網查下快遞是否已經到了(可能是多次),然後自己去取快遞;AIO就是快遞員送貨上門了(不用關注快遞進度)。配製項:protocol=”org.apache.coyote.http11.Http11AprProtocol”
備註:需在本地伺服器安裝APR庫。Tomcat7或Tomcat8在Win7或以上的系統中啟動預設使用這種方式。Linux如果安裝了apr和native,Tomcat直接啟動就支援apr。
Tomcat有幾種部署方式?在Tomcat中部署Web應用的方式主要有如下幾種:
利用Tomcat的自動部署。把web應用拷貝到webapps目錄。Tomcat在啟動時會載入目錄下的應用,並將編譯後的結果放入work目錄下。
使用Manager App控制檯部署。在tomcat主頁點選“Manager App” 進入應用管理控制檯,可以指定一個web應用的路徑或war檔案。
修改conf/server.xml檔案部署。修改conf/server.xml檔案,增加Context節點可以部署應用。
增加自定義的Web部署檔案。在conf/Catalina/localhost/ 路徑下增加 xyz.xml檔案,內容是Context節點,可以部署應用。
tomcat容器是如何建立servlet類例項?用到了什麼原理?當容器啟動時,會讀取在webapps目錄下所有的web應用中的web.xml檔案,然後對 xml檔案進行解析,並讀取servlet註冊資訊。然後,將每個應用中註冊的servlet類都進行載入,並通過 反射的方式例項化。(有時候也是在第一次請求時例項化)在servlet註冊時加上1如果為正數,則在一開始就例項化,如果不寫或為負數,則第一次請求例項化。Tomcat工作模式Tomcat作為servlet容器,有三種工作模式:
1、獨立的servlet容器,servlet容器是web伺服器的一部分;
2、程序內的servlet容器,servlet容器是作為web伺服器的外掛和java容器的實現,web伺服器外掛在內部地址空間開啟一個jvm使得java容器在內部得以執行。反應速度快但伸縮性不足;
3、程序外的servlet容器,servlet容器運行於web伺服器之外的地址空間,並作為web伺服器的外掛和java容器實現的結合。反應時間不如程序內但伸縮性和穩定性比程序內優;
進入Tomcat的請求可以根據Tomcat的工作模式分為如下兩類:
Tomcat作為應用程式伺服器:請求來自於前端的web伺服器,這可能是Apache, IIS, Nginx等;Tomcat作為獨立伺服器:請求來自於web瀏覽器;面試時問到Tomcat相關問題的機率並不高,正式因為如此,很多人忽略了對Tomcat相關技能的掌握,下面這一篇文章整理了Tomcat相關的系統架構,介紹了Server、Service、Connector、Container之間的關係,各個模組的功能,可以說把這幾個掌握住了,Tomcat相關的面試題你就不會有任何問題了!另外,在面試的時候你還要有意識無意識的往Tomcat這個地方引,就比如說常見的Spring MVC的執行流程,一個URL的完整呼叫鏈路,這些相關的題目你是可以往Tomcat處理請求的這個過程去說的!掌握了Tomcat這些技能,面試官一定會佩服你的!
學了本章之後你應該明白的是:
Server、Service、Connector、Container四大元件之間的關係和聯絡,以及他們的主要功能點;Tomcat執行的整體架構,請求是如何被一步步處理的;Engine、Host、Context、Wrapper相關的概念關係;Container是如何處理請求的;Tomcat用到的相關設計模式;Tomcat頂層架構俗話說,站在巨人的肩膀上看世界,一般學習的時候也是先總覽一下整體,然後逐個部分個個擊破,最後形成思路,了解具體細節,Tomcat的結構很複雜,但是 Tomcat 非常的模組化,找到了 Tomcat 最核心的模組,問題才可以遊刃而解,了解了 Tomcat 的整體架構對以後深入了解 Tomcat 來說至關重要!
先上一張Tomcat的頂層結構圖(圖A),如下:
Tomcat中最頂層的容器是Server,代表著整個伺服器,從上圖中可以看出,一個Server可以包含至少一個Service,即可以包含多個Service,用於具體提供服務。
Service主要包含兩個部分:Connector和Container。從上圖中可以看出 Tomcat 的心臟就是這兩個元件,他們的作用如下:
Connector用於處理連線相關的事情,並提供Socket與Request請求和Response響應相關的轉化;Container用於封裝和管理Servlet,以及具體處理Request請求;一個Tomcat中只有一個Server,一個Server可以包含多個Service,一個Service只有一個Container,但是可以有多個Connectors,這是因為一個服務可以有多個連線,如同時提供Http和Https連結,也可以提供向相同協議不同埠的連線,示意圖如下(Engine、Host、Context下面會說到):
多個 Connector 和一個 Container 就形成了一個 Service,有了 Service 就可以對外提供服務了,但是 Service 還要一個生存的環境,必須要有人能夠給她生命、掌握其生死大權,那就非 Server 莫屬了!所以整個 Tomcat 的生命週期由 Server 控制。
另外,上述的包含關係或者說是父子關係,都可以在tomcat的conf目錄下的server.xml配置檔案中看出,下圖是刪除了註釋內容之後的一個完整的server.xml配置檔案(Tomcat版本為8.0)
詳細的配置檔案內容可以到Tomcat官網檢視:
http://tomcat.apache.org/tomcat-8.0-doc/index.html
上邊的配置檔案,還可以通過下邊的一張結構圖更清楚的理解:
Server標籤設定的埠號為8005,shutdown=”SHUTDOWN” ,表示在8005埠監聽“SHUTDOWN”命令,如果接收到了就會關閉Tomcat。一個Server有一個Service,當然還可以進行配置,一個Service有多個Connector,Service左邊的內容都屬於Container的,Service下邊是Connector。
Tomcat頂層架構小結
Tomcat中只有一個Server,一個Server可以有多個Service,一個Service可以有多個Connector和一個Container;Server掌管著整個Tomcat的生死大權;Service 是對外提供服務的;Connector用於接受請求並將請求封裝成Request和Response來具體處理;Container用於封裝和管理Servlet,以及具體處理request請求;知道了整個Tomcat頂層的分層架構和各個元件之間的關係以及作用,對於絕大多數的開發人員來說Server和Service對我們來說確實很遠,而我們開發中絕大部分進行配置的內容是屬於Connector和Container的,所以接下來介紹一下Connector和Container。
Connector和Container的微妙關係由上述內容我們大致可以知道一個請求傳送到Tomcat之後,首先經過Service然後會交給我們的Connector,Connector用於接收請求並將接收的請求封裝為Request和Response來具體處理,Request和Response封裝完之後再交由Container進行處理,Container處理完請求之後再返回給Connector,最後在由Connector通過Socket將處理的結果返回給客戶端,這樣整個請求的就處理完了!
Connector最底層使用的是Socket來進行連線的,Request和Response是按照HTTP協議來封裝的,所以Connector同時需要實現TCP/IP協議和HTTP協議!
Tomcat既然需要處理請求,那麼肯定需要先接收到這個請求,接收請求這個東西我們首先就需要看一下Connector!
Connector架構分析
Connector用於接受請求並將請求封裝成Request和Response,然後交給Container進行處理,Container處理完之後在交給Connector返回給客戶端。
因此,我們可以把Connector分為四個方面進行理解:
Connector如何接受請求的?如何將請求封裝成Request和Response的?封裝完之後的Request和Response如何交給Container進行處理的?Container處理完之後如何交給Connector並返回給客戶端的?首先看一下Connector的結構圖(圖B),如下所示:
Connector就是使用ProtocolHandler來處理請求的,不同的ProtocolHandler代表不同的連線型別,比如:Http11Protocol使用的是普通Socket來連線的,Http11NioProtocol使用的是NioSocket來連線的。
其中ProtocolHandler由包含了三個部件:Endpoint、Processor、Adapter。
Endpoint用來處理底層Socket的網路連線,Processor用於將Endpoint接收到的Socket封裝成Request,Adapter用於將Request交給Container進行具體的處理。Endpoint由於是處理底層的Socket網路連線,因此Endpoint是用來實現TCP/IP協議的,而Processor用來實現HTTP協議的,Adapter將請求適配到Servlet容器進行具體的處理。Endpoint的抽象實現AbstractEndpoint裡面定義的Acceptor和AsyncTimeout兩個內部類和一個Handler介面。Acceptor用於監聽請求,AsyncTimeout用於檢查非同步Request的超時,Handler用於處理接收到的Socket,在內部呼叫Processor進行處理。至此,我們應該很輕鬆的回答1,2,3的問題了,但是4還是不知道,那麼我們就來看一下Container是如何進行處理的以及處理完之後是如何將處理完的結果返回給Connector的?
Container架構分析Container用於封裝和管理Servlet,以及具體處理Request請求,在Container內部包含了4個子容器,結構圖如下(圖C):
4個子容器的作用分別是:
Engine:引擎,用來管理多個站點,一個Service最多隻能有一個Engine;Host:代表一個站點,也可以叫虛擬主機,通過配置Host就可以新增站點;Context:代表一個應用程式,對應著平時開發的一套程式,或者一個WEB-INF目錄以及下面的web.xml檔案;Wrapper:每一Wrapper封裝著一個Servlet;下面找一個Tomcat的檔案目錄對照一下,如下圖所示:
Context和Host的區別是Context表示一個應用,我們的Tomcat中預設的配置下webapps下的每一個資料夾目錄都是一個Context,其中ROOT目錄中存放著主應用,其他目錄存放著子應用,而整個webapps就是一個Host站點。
我們訪問應用Context的時候,如果是ROOT下的則直接使用域名就可以訪問,例如:www.baidu.com,如果是Host(webapps)下的其他應用,則可以使用www.baidu.com/docs進行訪問,當然預設指定的根應用(ROOT)是可以進行設定的,只不過Host站點下預設的主應用是ROOT目錄下的。
看到這裡我們知道Container是什麼,但是還是不知道Container是如何進行請求處理的以及處理完之後是如何將處理完的結果返回給Connector的?別急!下邊就開始探討一下Container是如何進行處理的!
Container如何處理請求的Container處理請求是使用Pipeline-Valve管道來處理的!(Valve是閥門之意)
Pipeline-Valve是責任鏈模式,責任鏈模式是指在一個請求處理的過程中有很多處理者依次對請求進行處理,每個處理者負責做自己相應的處理,處理完之後將處理後的結果返回,再讓下一個處理者繼續處理。
但是!Pipeline-Valve使用的責任鏈模式和普通的責任鏈模式有些不同!區別主要有以下兩點:
每個Pipeline都有特定的Valve,而且是在管道的最後一個執行,這個Valve叫做BaseValve,BaseValve是不可刪除的;在上層容器的管道的BaseValve中會呼叫下層容器的管道。我們知道Container包含四個子容器,而這四個子容器對應的BaseValve分別在:StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve。
Pipeline的處理流程圖如下(圖D):
Connector在接收到請求後會首先呼叫最頂層容器的Pipeline來處理,這裡的最頂層容器的Pipeline就是EnginePipeline(Engine的管道);在Engine的管道中依次會執行EngineValve1、EngineValve2等等,最後會執行StandardEngineValve,在StandardEngineValve中會呼叫Host管道,然後再依次執行Host的HostValve1、HostValve2等,最後在執行StandardHostValve,然後再依次呼叫Context的管道和Wrapper的管道,最後執行到StandardWrapperValve。當執行到StandardWrapperValve的時候,會在StandardWrapperValve中建立FilterChain,並呼叫其doFilter方法來處理請求,這個FilterChain包含著我們配置的與請求相匹配的Filter和Servlet,其doFilter方法會依次呼叫所有的Filter的doFilter方法和Servlet的service方法,這樣請求就得到了處理!當所有的Pipeline-Valve都執行完之後,並且處理完了具體的請求,這個時候就可以將返回的結果交給Connector了,Connector在通過Socket的方式將結果返回給客戶端。總結至此,我們已經對Tomcat的整體架構有了大致的了解,從圖A、B、C、D可以看出來每一個元件的基本要素和作用。我們在腦海裡應該有一個大概的輪廓了!如果你面試的時候,讓你簡單的聊一下Tomcat,上面的內容你能脫口而出嗎?當你能夠脫口而出的時候,面試官一定會對你刮目相看的!