入門模塊僅作學習大綱梳理,忽略了具體操做指引。html
通道(Channel)、緩衝區(Buffer)、選擇器(Selector)mysql
1.請求被Connector組件接收,建立Request和Response對象。web
2.Connector將Request和Response交給Container,先經過Engine的pipeline組件流經內部的每一個Valve。spring
3.請求流轉到Host的pipeline組件中,而且通過內部Valve的過。sql
4.請求流轉到Context的pipeline組件中,而且通過內部的Valve的過濾。數據庫
5.請求流轉到Wrapper的pipeline組件中,而且通過內部的Valve的過濾。tomcat
6.Wrapper內部的WrapperValve建立FilterChain實例,調用指定的Servlet實例處理請求。安全
7.返回。服務器
Server:服務器的意思,表明整個tomcat服務器,一個tomcat只有一個Server;網絡
Service:Server中的一個邏輯功能層, 一個Server能夠包含多個Service;
Connector:稱做鏈接器,是Service的核心組件之一,一個Service能夠有多個Connector,主要是鏈接客戶端請求;
Container:Service的另外一個核心組件,按照層級有Engine,Host,Context,Wrapper四種,一個Service只有一個Engine,其主要做用是執
行業務邏輯;
Jasper:JSP引擎;
Session:會話管理;
Connector使用ProtocolHandler來處理請求的Endpoint用來處理底層Socket的網絡鏈接。
Processor用於將Endpoint接收到的Socket封裝成Request。
Adapter充當適配器,用於將Request轉換爲ServletRequest交給Container進行具體的處理。
ProtocolHandler由包含了三個部件:Endpoint、Processor,Adapter
service中的name是catalina,engine中的name也是catalina,這個就證實一個service就只有一個engine, 一個engine能夠有多個host主機
host,站點,虛擬主機。
Engine:引擎、只有一個定義了一個名爲Catalina的Engine
Host:站點、虛擬主機一個Engine包含多個Host的設計,使得一個服務器實例能夠承擔多個域名的服務,是很靈活的設計
Context:一個應用默認配置下webapps下的每一個目錄都是一個應用
Wrapper:一個Servlet
結合tomcat目錄結構理解上面的4個容器之間的關係
引用自:https://www.cnblogs.com/ghoster/p/7602158.html
1.主流的Java Web服務器,如Tomcat、Jetty、WebLogic、WebSphere等都實現了本身定義的類加載器(通常都不止一個)。由於一個功能健全的web服務器要解決一下幾個問題:
1)部署在一個服務器上的兩個web應用程序所使用的Java類庫能夠實現互相隔離。這是最基本的需求,兩個不一樣的應用程序可能會依賴同一個第三方類庫的不一樣版本,不能要求一個類庫在一個服務器中只有一份,服務器應當保證兩個應用程序的類庫能夠互相獨立使用
2)部署在同一個服務器上的兩個Web應用程序所使用的Java類庫能夠互相共享。這個需求也很是很常見,如,用戶可能有10各使用Spring組織的應用程序部署在同一臺服務器上,若是把10份Spring分別存放在各個應用程序的隔離目錄中,將會是很大的資源浪費-這主要不是浪費磁盤空間的問題,而是指類庫在使用時都要被加載到服務器內存,若是類庫不能共享,虛擬機的方法區就會很容易出現過分膨脹的風險
3)服務器須要儘量地保證自身的安全不受部署的Web應用程序影響。目前,有許多主流的Java Web服務器自身也是使用Java語言來實現的。所以,服務器自己也有類庫依賴的問題,通常來講,基於安全考慮,服務器所使用的類庫應該與應用程序的類庫相互獨立
4)支持jsp應用的Web服務器,大多數都須要支持HotSwap功能。咱們知道,jsp文件最終要編譯成Java Class才能由虛擬機執行,但jsp文件因爲其純文本存儲的特性,運行時修改的機率遠遠大於第三方類庫或程序自身的Class文件。並且ASP、PHP和JSP這些網頁應用也把修改後無需重啓做爲一個很大的「優點」來看待,所以,「主流」的Web服務器都會支持JSP的熱替換,固然也有「非主流」的,如運行在生產模式下的WebLogic服務器默認就不會處理JSP文件的變化
因爲存在上述問題,在部署Web應用時,單獨的一個ClassPath就沒法知足需求了,因此各類Web服務器都「不約而同」地提供了好幾個ClassPath路徑供用戶存放第三方類庫,這些路徑通常都以lib或classes命名,被放置到不一樣路徑中的類庫,具有不一樣的訪問範圍和服務對象,一般,每個目錄都會有一個相應的自定義類加載器去加載放置在裏面的Java類庫。
2.Tomcat對用戶類庫與類加載器的規劃
在其目錄結構下有三組目錄(「/common/*」、「/server/*」、「/shared/*」)能夠存放Java類庫,另外還能夠加上Web應用程序自己的目錄「/WEB-INF/*」,一共4組,把Java類庫放置在這些目錄中的含義分別以下:
1)放置在/commom目錄中:類庫可被Tomcat和全部的Web應用程序共同使用
2)放置在/server目錄中:類庫可被Tomcat使用,對全部的Web應用程序都不可見
3)放置在/shared目錄中:類庫可被全部的Web應用程序所共同使用,但對Tomcat本身不可見
4)放置在/WebApp/WEB-INF目錄中:類庫僅僅能夠被此Web應用程序使用,對Tomcat和其餘Web應用程序都不可見
爲了支持這套目錄結構,並對目錄裏面的類庫進行加載和隔離,Tomcat自定義了多個類加載器,這些類加載器按照經典的雙親委派模型來實現,所下圖:
最上面的三個類加載器是JDK默認提供的類加載器,這三個加載器的的做用以前也說過,這裏再也不贅述了,能夠在http://www.cnblogs.com/ghoster/p/7594224.html簡單瞭解。而CommonClassLoader、CatalinaClassLoader、SharedClassLoader和WebAppClassLoader則是Tomcat本身定義的類加載器,他們分別加載/common/*、/server/*、/shared/*和/WebApp/WEB-INF/*中的Java類庫。其中WebApp類加載器和jsp類加載器一般會存在多個實例,每個Web應用程序對應一個WebApp類加載器,每個jsp文件對應一個Jsp類加載器
從上圖的委派關係能夠看出,CommonClassLoader能加載的類均可以被CatalinaClassLoader和SharedClassLoader使用,而CatalinaClassLoader和SharedClassLoader本身能加載的類則與對方相互隔離。WebAppClassLoader可使用SharedClassLoader加載到的類,但各個WebAppClassLoader實例之間相互隔離。而JasperLoader的加載範圍僅僅是這個JSP文件所編譯出來的哪個Class,它出現的目的就是爲了被丟棄:當服務器檢測到JSP文件被修改時,會替換掉目前的JasperLoader的實例,並經過在創建一個新的Jsp類加載器來實現JSP文件的HotSwap功能
需求背景:在使用多數據源的狀況下,同時鏈接某大廠魔改的數據庫mppdb和pgsql數據庫的時候。出現了沒法同時加載mppdb和pgsql的驅動的問題。
緣由分析:spring在啓動時會調用應用類加載器加載org目錄下的.class文件,同時spring自定義類加載器分別加載BOOT-INF,META-INF 目錄下的文件,mppdb 與pgsql驅動的本質都是.jar文件,因此會放在META-INF目錄下的lib目錄下。
又由於mppdb是某國內大廠以pgsql爲藍本魔改的,遺留下一個問題,mppdb與mysql驅動的類名是徹底一致的。而兩驅動都放在lib目錄下,由同一個類加載器來加載,就會出現如下狀況:當第一個驅動pgsql加載時,使用雙親機制正常加載,
當第二個驅動mppdb再次加載時,會判斷該類是否加載過,此時,因爲類加載器一致,類名一致,類加載器會誤認爲mppdb驅動已經加載過了,實際是以前加載的pgsql驅動,因此spring不會再去加載mppdb,而是從緩衝中把pgsql的驅動拋出,
從而致使了,spring在啓動時沒法同時加載mppdn驅動和pgsql驅動。
解決方案:
方案一:遵循雙親委派模型
在spring容器啓動後(此時spring已經加載到其中一個驅動,假設是pgsql驅動),新開一個jvm進程,在該進程中使用擴展類加載器加載mppdb驅動,根據雙親委派模型,擴展類加載器是應用類加載器的父類,當須要加載驅動時會優先委派父類加載,
因此同一個類在父類加載器和子類加載器都能加載的狀況下,父類加載器總能優先加載的。這樣就保證了,新起的進程老是能加載到擴展類加載器加載的mppdb驅動。
方案二:打破雙親委派模型
在spring容器啓動後(此時spring已經加載到其中一個驅動,假設是pgsql驅動),沒必要新開進程,仍是在該spring的進程內,使用應用類加載器XMLClassLoader去加載mppdb驅動,若是此時使用雙親委派模型,會加載到spring初始化時加載到的驅動,即pgsql驅動,
故而 須要將XMLClassLoader 的父加載器設置爲null,禁止其父加載器加載,而由其本身加載,便可以成功加載mppdb驅動,具體實現涉及公司信息安全,在此僅提供問題解決思路。