Tomcat是什么?
Tomcat 服務器Apache軟件基金會項目中的一個核心項目锐帜,是一個免費的開放 源代碼的Web 應用服務
器祭示,屬于輕量級應用服務器,在中小型系統(tǒng)和并發(fā)訪問 用戶不是很多的場合下被普遍使用辟拷,是開發(fā)和調(diào)
試JSP 程序的首選。
Tomcat的缺省端口是多少环凿,怎么修改
找到Tomcat目錄下的conf文件夾
進入conf文件夾里面找到server.xml文件
打開server.xml文件
在server.xml文件里面找到下列信息
把Connector標簽的8080端口改成你想要的端口
tomcat 有哪幾種Connector 運行模式(優(yōu)化)梧兼?
下面,我們先大致了解Tomcat Connector的三種運行模式智听。
BIO:同步并阻塞 一個線程處理一個請求羽杰。缺點:并發(fā)量高時,線程數(shù)較 多到推,浪費資源考赛。
Tomcat7或以下,在Linux系統(tǒng)中默認使用這種方式莉测。
配制項:protocol=”HTTP/1.1”
NIO:同步非阻塞IO 利用Java的異步IO處理颜骤,可以通過少量的線程處理大量的請求,可以復用同一
個線程處理多個connection(多路復用)捣卤。
Tomcat8在Linux系統(tǒng)中默認使用這種方式忍抽。
Tomcat7必須修改Connector配置來啟動。
配制項:protocol=”org.apache.coyote.http11.Http11NioProtocol”
備注:我們常用的Jetty董朝,Mina鸠项,ZooKeeper等都是基于java nio實現(xiàn).
APR:即Apache Portable Runtime,從操作系統(tǒng)層面解決io阻塞問 題子姜。AIO方式祟绊,異步非阻塞
IO(Java NIO2又叫AIO) 主要與NIO的區(qū)別 主要是操作系統(tǒng)的底層區(qū)別.可以做個比喻:比作快遞,
NIO就是網(wǎng)購后要自 己到官網(wǎng)查下快遞是否已經(jīng)到了(可能是多次)哥捕,然后自己去取快遞牧抽;AIO就 是
快遞員送貨上門了(不用關(guān)注快遞進度)。
配制項:protocol=”org.apache.coyote.http11.Http11AprProtocol”
備注:需在本地服務器安裝APR庫遥赚。Tomcat7或Tomcat8在Win7或以上的系統(tǒng) 中啟動默認使用這
種方式扬舒。Linux如果安裝了apr和native,Tomcat直接啟動就 支持apr凫佛。
Tomcat有幾種部署方式呼巴?
在Tomcat中部署Web應用的方式主要有如下幾種:
利用Tomcat的自動部署。
把web應用拷貝到webapps目錄御蒲。Tomcat在啟動時會加載目錄下的應用衣赶,并將 編譯后的結(jié)果放入
work目錄下。
使用Manager App控制臺部署厚满。
在tomcat主頁點擊“Manager App” 進入應用管理控制臺府瞄,可以指定一個 web應用的路徑或war文
件。
修改conf/server.xml文件部署。
修改conf/server.xml文件遵馆,增加Context節(jié)點可以部署應用鲸郊。
增加自定義的Web部署文件。
在conf/Catalina/localhost/ 路徑下增加 xyz.xml文件货邓,內(nèi)容是Context節(jié)點秆撮, 可以部署應用
tomcat容器是如何創(chuàng)建servlet類實例?用到了什么 原
理换况?
1. 當容器啟動時职辨,會讀取在webapps目錄下所有的web應用中的web.xml 文件,然后對 xml文件進
行解析戈二,并讀取servlet注冊信息舒裤。然后,將每個 應用中注冊的servlet類都進行加載觉吭,并通過 反射
的方式實例化腾供。(有時候 也是在第一次請求時實例化)
2. 在servlet注冊時加上1如果為正數(shù),則在一開始就實例化鲜滩,如果不寫或 為負數(shù)伴鳖,則第一次請求實例
化。
Tomcat工作模式
1 <Service name="Catalina">
2 <Connector port="8080" protocol="HTTP/1.1"
3 connectionTimeout="20000"
4 redirectPort="8443" />
Tomcat作為servlet容器徙硅,有三種工作模式:
1. 獨立的servlet容器榜聂,servlet容器是web服務器的一部分;
2. 進程內(nèi)的servlet容器闷游,servlet容器是作為web服務器的插件和java容器的實 現(xiàn),web服務器插件在
內(nèi)部地址空間打開一個jvm使得java容器在內(nèi)部得以運行贴汪。反 應速度快但伸縮性不足脐往;
3. 進程外的servlet容器,servlet容器運行于web服務器之外的地址空間扳埂,并作 為web服務器的插件
和java容器實現(xiàn)的結(jié)合业簿。反應時間不如進程內(nèi)但伸縮性和穩(wěn)定性 比進程內(nèi)優(yōu); 進入Tomcat的請求
可以根據(jù)Tomcat的工作模式分為如下兩類:
Tomcat作為應用程序服務器:請求來自于前端的web服務器阳懂,這可能是 Apache, IIS, Nginx等梅尤;
Tomcat作為獨立服務器:請求來自于web瀏覽器;
面試時問到Tomcat相關(guān)問題的幾率并不高岩调,正式因為如此巷燥,很多人忽略了對 Tomcat相關(guān)技能的掌握,
下面這一篇文章整理了Tomcat相關(guān)的系統(tǒng)架構(gòu)号枕,介 紹了Server缰揪、Service、Connector葱淳、Container之間
的關(guān)系钝腺,各個模塊的功 能抛姑,可以說把這幾個掌握住了,Tomcat相關(guān)的面試題你就不會有任何問題了艳狐!
另外定硝,在面試的時候你還要有意識無意識的往Tomcat這個地方引,就比如說常 見的Spring MVC的執(zhí)行
流程毫目,一個URL的完整調(diào)用鏈路蔬啡,這些相關(guān)的題目你是 可以往Tomcat處理請求的這個過程去說的!掌握
了Tomcat這些技能蒜茴,面試官 一定會佩服你的星爪!
學了本章之后你應該明白的是:
Server、Service粉私、Connector顽腾、Container四大組件之間的關(guān)系和聯(lián)系,以及他 們的主要功能點诺核;
Tomcat執(zhí)行的整體架構(gòu)抄肖,請求是如何被一步步處理的;
Engine窖杀、Host漓摩、Context、Wrapper相關(guān)的概念關(guān)系入客;
Container是如何處理請求的管毙;
Tomcat用到的相關(guān)設計模式;
Tomcat頂層架構(gòu)
俗話說桌硫,站在巨人的肩膀上看世界夭咬,一般學習的時候也是先總覽一下整體,然后 逐個部分個個擊破铆隘,最
后形成思路卓舵,了解具體細節(jié),Tomcat的結(jié)構(gòu)很復雜膀钠,但 是 Tomcat 非常的模塊化掏湾,找到了 Tomcat 最
核心的模塊,問題才可以游刃而 解肿嘲,了解了 Tomcat 的整體架構(gòu)對以后深入了解 Tomcat 來說至關(guān)重
要融击! 先上一張Tomcat的頂層結(jié)構(gòu)圖(圖A),如下:
Tomcat中最頂層的容器是Server雳窟,代表著整個服務器砚嘴,從上圖中可以看出,一 個Server可以包含至少
一個Service,即可以包含多個Service际长,用于具體提供服 務耸采。
Service主要包含兩個部分:Connector和Container。從上圖中可以看出 Tomcat 的心臟就是這兩個組
件工育,他們的作用如下:
Connector用于處理連接相關(guān)的事情虾宇,并提供Socket與Request請求和 Response響應相關(guān)的轉(zhuǎn)化;
Container用于封裝和管理Servlet,以及具體處理Request請求如绸;
一個Tomcat中只有一個Server嘱朽,一個Server可以包含多個Service,一個 Service只有一個Container怔接,
但是可以有多個Connectors搪泳,這是因為一個服務 可以有多個連接,如同時提供Http和Https鏈接扼脐,也可
以提供向相同協(xié)議不同端 口的連接岸军,示意圖如下(Engine、Host瓦侮、Context下面會說到):
多個 Connector 和一個 Container 就形成了一個 Service艰赞,有了 Service 就可 以對外提供服務了,但是
Service 還要一個生存的環(huán)境肚吏,必須要有人能夠給她生 命方妖、掌握其生死大權(quán),那就非 Server 莫屬了罚攀!所
以整個 Tomcat 的生命周期由 Server 控制党觅。
另外,上述的包含關(guān)系或者說是父子關(guān)系斋泄,都可以在tomcat的conf目錄下的 server.xml配置文件中看
出杯瞻,下圖是刪除了注釋內(nèi)容之后的一個完整的 server.xml配置文件(Tomcat版本為8.0)
詳細的配置文件內(nèi)容可以到Tomcat官網(wǎng)查看:Tomcat配置文件
上邊的配置文件,還可以通過下邊的一張結(jié)構(gòu)圖更清楚的理解:
Server標簽設置的端口號為8005是己,shutdown=”SHUTDOWN” 又兵,表示在 8005端口監(jiān)聽“SHUTDOWN”命
令任柜,如果接收到了就會關(guān)閉Tomcat卒废。一個 Server有一個Service,當然還可以進行配置宙地,一個Service有
多個Connector摔认, Service左邊的內(nèi)容都屬于Container的,Service下邊是Connector宅粥。
Tomcat頂層架構(gòu)小結(jié)
1. Tomcat中只有一個Server参袱,一個Server可以有多個Service,一個 Service可以有多個Connector和
一個Container;
2. Server掌管著整個Tomcat的生死大權(quán)抹蚀;
3. Service 是對外提供服務的剿牺;
4. Connector用于接受請求并將請求封裝成Request和Response來具體 處理;
5. Container用于封裝和管理Servlet环壤,以及具體處理request請求晒来;
知道了整個Tomcat頂層的分層架構(gòu)和各個組件之間的關(guān)系以及作用,對于絕大 多數(shù)的開發(fā)人員來說
Server和Service對我們來說確實很遠郑现,而我們開發(fā)中絕大 部分進行配置的內(nèi)容是屬于Connector和
Container的湃崩,所以接下來介紹一下 Connector和Container。
Connector和Container的微妙關(guān)系
由上述內(nèi)容我們大致可以知道一個請求發(fā)送到Tomcat之后接箫,首先經(jīng)過Service然 后會交給我們的
Connector攒读,Connector用于接收請求并將接收的請求封裝為 Request和Response來具體處理,
Request和Response封裝完之后再交由 Container進行處理辛友,Container處理完請求之后再返回給
Connector薄扁,最后在 由Connector通過Socket將處理的結(jié)果返回給客戶端,這樣整個請求的就處理 完
了瞎领!
Connector最底層使用的是Socket來進行連接的泌辫,Request和Response是按照 HTTP協(xié)議來封裝的,所
以Connector同時需要實現(xiàn)TCP/IP協(xié)議和HTTP協(xié)議九默!
Tomcat既然需要處理請求震放,那么肯定需要先接收到這個請求,接收請求這個東 西我們首先就需要看一
下Connector驼修!
Connector架構(gòu)分析
Connector用于接受請求并將請求封裝成Request和Response殿遂,然后交給 Container進行處理,
Container處理完之后在交給Connector返回給客戶端乙各。 因此墨礁,我們可以把Connector分為四個方面進行
理解:
1. Connector如何接受請求的?
2. 如何將請求封裝成Request和Response的耳峦?
3. 封裝完之后的Request和Response如何交給Container進行處理的恩静?
4. Container處理完之后如何交給Connector并返回給客戶端的? 首先看一下Connector的結(jié)構(gòu)圖蹲坷,
如下所示:
Connector就是使用ProtocolHandler來處理請求的驶乾,不同的ProtocolHandler 代表不同的連接類型,比
如:Http11Protocol使用的是普通Socket來連接的循签, Http11NioProtocol使用的是NioSocket來連接
的级乐。
其中ProtocolHandler由包含了三個部件:Endpoint、Processor县匠、Adapter风科。
1. Endpoint用來處理底層Socket的網(wǎng)絡連接撒轮,Processor用于將 Endpoint接收到的Socket封裝成
Request,Adapter用于將Request交給 Container進行具體的處理贼穆。
2. Endpoint由于是處理底層的Socket網(wǎng)絡連接题山,因此Endpoint是用來實 現(xiàn)TCP/IP協(xié)議的掏呼,而
Processor用來實現(xiàn)HTTP協(xié)議的盅安,Adapter將請求適 配到Servlet容器進行具體的處理推溃。
3. Endpoint的抽象實現(xiàn)AbstractEndpoint里面定義的Acceptor和 AsyncTimeout兩個內(nèi)部類和一個
Handler接口毁腿。Acceptor用于監(jiān)聽請 求斧拍,AsyncTimeout用于檢查異步Request的超時己儒,Handler用
于處理接收 到的Socket记焊,在內(nèi)部調(diào)用Processor進行處理芳杏。
至此豫领,我們應該很輕松的回答1抡柿,2,3的問題了等恐,但是4還是不知道洲劣,那么我們 就來看一下Container是
如何進行處理的以及處理完之后是如何將處理完的結(jié)果 返回給Connector的?
Container架構(gòu)分析
Container用于封裝和管理Servlet课蔬,以及具體處理Request請求囱稽,在Container 內(nèi)部包含了4個子容器,
結(jié)構(gòu)圖如下:
4個子容器的作用分別是:
1. Engine:引擎二跋,用來管理多個站點战惊,一個Service最多只能有一個 Engine;
2. Host:代表一個站點扎即,也可以叫虛擬主機吞获,通過配置Host就可以添加 站點;
3. Context:代表一個應用程序谚鄙,對應著平時開發(fā)的一套程序各拷,或者一個 WEB-INF目錄以及下面的
web.xml文件;
4. Wrapper:每一Wrapper封裝著一個Servlet闷营; 下面找一個Tomcat的文件目錄對照一下烤黍,如下圖所
示:
Context和Host的區(qū)別是Context表示一個應用,我們的Tomcat中默認的配置 下webapps下的每一個文
件夾目錄都是一個Context傻盟,其中ROOT目錄中存放著 主應用速蕊,其他目錄存放著子應用,而整個
webapps就是一個Host站點莫杈。
我們訪問應用Context的時候互例,如果是ROOT下的則直接使用域名就可以訪問奢入, 例如:
www.baidu.com筝闹,如果是Host(webapps)下的其他應用媳叨,則可以使 用www.baidu.com/docs進行訪
問,當然默認指定的根應用(ROOT)是可以 進行設定的关顷,只不過Host站點下默認的主應用是ROOT目
錄下的糊秆。
看到這里我們知道Container是什么,但是還是不知道Container是如何進行請 求處理的以及處理完之后
是如何將處理完的結(jié)果返回給Connector的议双?別急痘番!下 邊就開始探討一下Container是如何進行處理
的!
Container如何處理請求的
Container處理請求是使用Pipeline-Valve管道來處理的F教怠(Valve是閥門之 意)
Pipeline-Valve是責任鏈模式汞舱,責任鏈模式是指在一個請求處理的過程中有很多 處理者依次對請求進行
處理,每個處理者負責做自己相應的處理宗雇,處理完之后將 處理后的結(jié)果返回昂芜,再讓下一個處理者繼續(xù)處
理。
但是赔蒲!Pipeline-Valve使用的責任鏈模式和普通的責任鏈模式有些不同泌神!區(qū)別主 要有以下兩點:
每個Pipeline都有特定的Valve,而且是在管道的最后一個執(zhí)行舞虱,這個 Valve叫做BaseValve欢际,BaseValve
是不可刪除的;
在上層容器的管道的BaseValve中會調(diào)用下層容器的管道矾兜。
我們知道Container包含四個子容器损趋,而這四個子容器對應的BaseValve分別
在:StandardEngineValve、StandardHostValve椅寺、StandardContextValve舶沿、
StandardWrapperValve。
Pipeline的處理流程圖如下:
Connector在接收到請求后會首先調(diào)用最頂層容器的Pipeline來處 理配并,這里的最頂層容器的
Pipeline就是EnginePipeline(Engine的管 道)括荡;
在Engine的管道中依次會執(zhí)行EngineValve1、EngineValve2等等溉旋, 最后會執(zhí)行
StandardEngineValve畸冲,在StandardEngineValve中會調(diào)用 Host管道,然后再依次執(zhí)行Host的
HostValve1观腊、HostValve2等邑闲,最后在 執(zhí)行StandardHostValve,然后再依次調(diào)用Context的管道和
Wrapper的 管道梧油,最后執(zhí)行到StandardWrapperValve苫耸。
當執(zhí)行到StandardWrapperValve的時候,會在 StandardWrapperValve中創(chuàng)建FilterChain儡陨,并調(diào)
用其doFilter方法來處 理請求褪子,這個FilterChain包含著我們配置的與請求相匹配的Filter和
Servlet量淌,其doFilter方法會依次調(diào)用所有的Filter的doFilter方法和Servlet 的service方法,這樣請
求就得到了處理嫌褪!
當所有的Pipeline-Valve都執(zhí)行完之后呀枢,并且處理完了具體的請求, 這個時候就可以將返回的結(jié)果
交給Connector了笼痛,Connector在通過 Socket的方式將結(jié)果返回給客戶端裙秋。