Tomcat 架構

一、Http工作原理

????????HTTP協議是瀏覽器與服務器之間的數據傳送協議。作為應用層協議,HTTP是基于TCP/IP協議來傳遞數據的(HTML文件、圖片、查詢結果等),HTTP協議不涉及數據包(Packet)傳輸,主要規定了客戶端和服務器之間的通信格式。

從圖上你可以看到,這個過程是:

1) 用戶通過瀏覽器進行了一個操作,比如輸入網址并回車,或者是點擊鏈接,接著瀏覽器獲取了這個事件。

2) 瀏覽器向服務端發出TCP連接請求。

3) 服務程序接受瀏覽器的連接請求,并經過TCP三次握手建立連接。

4) 瀏覽器將請求數據打包成一個HTTP協議格式的數據包。

5) 瀏覽器將該數據包推入網絡,數據包經過網絡傳輸,最終達到端服務程序。

6) 服務端程序拿到這個數據包后,同樣以HTTP協議格式解包,獲取到客戶端的意圖。

7) 得知客戶端意圖后進行處理,比如提供靜態文件或者調用服務端程序獲得動態結果。

8) 服務器將響應結果(可能是HTML或者圖片等)按照HTTP協議格式打包。

9) 服務器將響應數據包推入網絡,數據包經過網絡傳輸最終達到到瀏覽器。

10) 瀏覽器拿到數據包后,以HTTP協議的格式解包,然后解析數據,假設這里的數據是HTML。

11) 瀏覽器將HTML文件展示在頁面上。

在這個過程中都做了些什么事情呢?主要是接受連接、解析請求數據、處理請求和發送響應這幾個步驟。

二、Tomcat的整體架構

????????1.Http服務器請求處理

????????瀏覽器發給服務端的是一個HTTP格式的請求,HTTP服務器收到這個請求后,需要調用服務端程序來處理,所謂的服務端程序就是你寫的Java類,一般來說不同的請求需要由不同的Java類來處理。

????????圖1,表示HTTP服務器直接調用具體業務類,它們是緊耦合的。

????????圖2,HTTP服務器不直接調用業務類,而是把請求交給容器來處理,容器通過Servlet接口調用業務類。因此Servlet接口和Servlet容器的出現,達到了HTTP服務器與業務類解耦的目的。而Servlet接口和Servlet容器這一整套規范叫作Servlet規范。Tomcat按照Servlet規范的要求實現了Servlet容器,同時它們也具有HTTP服務器的功能。作為Java程序員,如果我們要實現新的業務功能,只需要實現一個Servlet,并把它注冊到Tomcat(Servlet容器)中,剩下的事情就由Tomcat幫我們處理了。

????????2.Servlet容器工作流程

????????為了解耦,HTTP服務器不直接調用Servlet,而是把請求交給Servlet容器來處理,那Servlet容器又是怎么工作的呢?

????????當客戶請求某個資源時,HTTP服務器會用一個ServletRequest對象把客戶的請求信息封裝起來,然后調用Servlet容器的service方法,Servlet容器拿到請求后,根據請求的URL和Servlet的映射關系,找到相應的Servlet,如果Servlet還沒有被加載,就用反射機制創建這個Servlet,并調用Servlet的init方法來完成初始化,接著調用Servlet的service方法來處理請求,把ServletResponse對象返回給HTTP服務器,HTTP服務器會把響應發送給客戶端。

????????3.Tomcat整體架構

????????我們知道如果要設計一個系統,首先是要了解需求,我們已經了解了Tomcat要實現兩個核心功能:

????????處理Socket連接,負責網絡字節流與Request和Response對象的轉化。

????????加載和管理Servlet,以及具體處理Request請求。

????????因此Tomcat設計了兩個核心組件連接器(Connector)和容器(Container)來分別做這兩件事情。連接器負責對外交流,容器負責內部處理。

三、連接器 - Coyote

????????1.架構介紹

????????Coyote 是Tomcat的連接器框架的名稱, 是Tomcat服務器提供的供客戶端訪問的外部接口。客戶端通過Coyote與服務器建立連接、發送請求并接受響應 。

????????Coyote 封裝了底層的網絡通信(Socket 請求及響應處理),為Catalina 容器提供了統一的接口,使Catalina 容器與具體的請求協議及IO操作方式完全解耦。Coyote 將Socket輸入轉換封裝為Request對象,交由Catalina 容器進行處理,處理請求完成后, Catalina 通過Coyote 提供的Response 對象將結果寫入輸出流 。

????????Coyote 作為獨立的模塊,只負責具體協議和IO的相關操作,與Servlet規范實現沒有直接關系,因此即便是Request和Response對象也并未實現Servlet規范對應的接口, 而是在Catalina 中將他們進一步封裝為ServletRequest 和 ServletResponse 。

????????2.I/O模型與協議

????????在Coyote中,Tomcat支持的多種I/O模型和應用層協議,具體包含哪些I/O模型和應用層協議,請看下表:

????????Tomcat支持的IO模型(自8.5/9.0版本起,Tomcat移除了對 BIO的支持):

????????Tomcat支持的應用層協議:

????????協議分層:

????????在 8.0 之前 , Tomcat 默認采用的I/O方式為 BIO , 之后改為 NIO。 無論 NIO、NIO2還是 APR, 在性能方面均優于以往的BIO。 如果采用APR, 甚至可以達到 Apache HTTP Server 的影響性能。

????????Tomcat為了實現支持多種I/O模型和應用層協議,一個容器可能對接多個連接器,就好比一個房間有多個門。但是單獨的連接器或者容器都不能對外提供服務,需要把它們組裝起來才能工作,組裝后這個整體叫作Service組件。這里請你注意,Service本身沒有做什么重要的事情,只是在連接器和容器外面多包了一層,把它們組裝在一起。Tomcat內可能有多個Service,這樣的設計也是出于靈活性的考慮。通過在Tomcat中配置多個Service,可以實現通過不同的端口號來訪問同一臺機器上部署的不同應用。

????????3.連接器組件

????????連接器中的各個組件的作用如下:

????????EndPoint

????????1) EndPoint : Coyote 通信端點,即通信監聽的接口,是具體Socket接收和發送處理器,是對傳輸層的抽象,因此EndPoint用來實現TCP/IP協議的。

????????2) Tomcat 并沒有EndPoint 接口,而是提供了一個抽象類AbstractEndpoint,里面定義了兩個內部類:Acceptor和SocketProcessor。Acceptor用于監聽Socket連接請求。SocketProcessor用于處理接收到的Socket請求,它實現Runnable接口,在Run方法里調用協議處理組件Processor進行處理。為了提高處理能力,SocketProcessor被提交到線程池來執行。而這個線程池叫作執行器(Executor)。

????????Processor

????????Processor : Coyote 協議處理接口 ,如果說EndPoint是用來實現TCP/IP協議的,那么Processor用來實現HTTP協議,Processor接收來自EndPoint的Socket,讀取字節流解析成Tomcat Request和Response對象,并通過Adapter將其提交到容器處理,Processor是對應用層協議的抽象。

????????ProtocolHandler

????????ProtocolHandler: Coyote協議接口,通過Endpoint和Processor,實現針對具體協議的處理能力。

????????Tomcat 按照協議和I/O 提供了6個實現類 : AjpNioProtocol、AjpAprProtocol、AjpNio2Protocol、Http11NioProtocol、Http11Nio2Protocol、Http11AprProtocol。

????????我們在配置tomcat/conf/server.xml時,至少要指定具體的ProtocolHandler,當然也可以指定協議名稱,如:HTTP/1.1 ,如果安裝了APR,那么將使用Http11AprProtocol,否則使用 Http11NioProtocol。

????????Adapter

????????由于協議不同,客戶端發過來的請求信息也不盡相同,Tomcat定義了自己的Request類來“存放”這些請求信息。ProtocolHandler接口負責解析請求并生成Tomcat Request類。但是這個Request對象不是標準的ServletRequest,也就意味著,不能用Tomcat Request作為參數來調用容器。Tomcat設計者的解決方案是引入CoyoteAdapter,這是適配器模式的經典運用,連接器調用CoyoteAdapter的Sevice方法,傳入的是TomcatRequest對象,CoyoteAdapter負責將Tomcat Request轉成ServletRequest,再調用容器的Service方法。

四、容器 - Catalina

????????Tomcat是一個由一系列可配置的組件構成的Web容器,而Catalina是Tomcat的servlet容器。

????????Catalina 是Servlet 容器實現,包含了之前講到的所有的容器組件,以及后續章節涉及到的安全、會話、集群、管理等Servlet 容器架構的各個方面。它通過松耦合的方式集成Coyote,以完成按照請求協議進行數據讀寫。同時,它還包括我們的啟動入口、Shell程序等。

????????1.Catalina 地位

????????Tomcat的模塊分層結構圖,如下:

????????Tomcat 本質上就是一款 Servlet 容器,因此Catalina 才是Tomcat 的核心,其他模塊都是為Catalina 提供支撐的。比如 :通過Coyote 模塊提供鏈接通信,Jasper 模塊提供JSP引擎,Naming 提供JNDI 服務,Juli 提供日志服務。

????????2.Catalina 結構

????????Catalina 的主要組件結構如下:

????????如上圖所示,Catalina負責管理Server,而Server表示著整個服務器。Server下面有多個服務Service,每個服務都包含著多個連接器組件Connector(Coyote 實現)和一個容器組件Container。在Tomcat 啟動的時候, 會初始化一個Catalina的實例。

????????Catalina 各個組件的職責:

????????3.Container 結構

????????Tomcat設計了4種容器,分別是Engine、Host、Context和Wrapper。這4種容器不是平行關系,而是父子關系。, Tomcat通過一種分層的架構,使得Servlet容器具有很好的靈活性。

????????各個組件的含義 :

????????我們也可以再通過Tomcat的server.xml配置文件來加深對Tomcat容器的理解。Tomcat采用了組件化的設計,它的構成組件都是可配置的,其中最外層的是Server,其他組件按照一定的格式要求配置在這個頂層容器中。

????????那么,Tomcat是怎么管理這些容器的呢?你會發現這些容器具有父子關系,形成一個樹形結構,你可能馬上就想到了設計模式中的組合模式。沒錯,Tomcat就是用組合模式來管理這些容器的。具體實現方法是,所有容器組件都實現了Container接口,因此組合模式可以使得用戶對單容器對象和組合容器對象的使用具有一致性。這里單容器對象指的是最底層的Wrapper,組合容器對象指的是上面的Context、Host或者Engine。

????????Container 接口中提供了以下方法(截圖中知識一部分方法):

????????在上面的接口看到了getParent、SetParent、addChild和removeChild等方法。

????????Container接口擴展了LifeCycle接口,LifeCycle接口用來統一管理各組件的生命周期。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/713719.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/713719.shtml
英文地址,請注明出處:http://en.pswp.cn/news/713719.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c語言之字符串的輸入和輸出

c語言在輸出字符串時&#xff0c;用格式符‘%s"&#xff0c;代碼比較簡潔 如果說數組長度大于字符串長度&#xff0c;也只輸出\0前的內容 字符串默認后面有\0. 如果字符串有多個\0&#xff0c;會默認在第一個\0結束 #include<stdio.h> int main() {int i;char a…

GO數組切片

1. 數組 數組是一個由固定長度的特定類型元素組成的序列&#xff0c;一個數組可以由零個或多個元素組成。 因為數組的長度是固定的&#xff0c;所以在Go語言中很少直接使用數組。 Go語言數組的聲明&#xff1a; var 數組變量名 [元素數量]Type 1 數組變量名&#xff1a;數…

本地快速部署谷歌開放模型Gemma教程(基于WasmEdge)

本地快速部署谷歌開放模型Gemma教程&#xff08;基于WasmEdge&#xff09; 一、介紹 Gemma二、部署 Gemma2.1 部署工具2.1 部署步驟 三、構建超輕量級 AI 代理四、總結 一、介紹 Gemma Gemma是一系列輕量級、最先進的開放式模型&#xff0c;采用與創建Gemini模型相同的研究和技…

持續集成(CICD)- Jenkins插件安裝失敗解決辦法

解決辦法&#xff1a;將插件安裝更新源需要改成國內鏡像源 具體步驟如下&#xff1a; 步驟一&#xff1a;修改Jenkins工作目錄下的 hudson.model.UpdateCenter.xml 文件&#xff0c;將url 改為http://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json 步驟二…

RuoYi-Vue-Plus功能分析-jackson配置

文章目錄 前言一、配置文件二、配置類三、注解四、json工具類1. 工具內容2. 使用工具 前言 前端在給我發送請求的時候一般包含三個部分url&#xff0c;header&#xff0c;body。那么就會涉及我們后端如何接收這些請求參數并且我們處理完畢參數后前端又如何接收參數 通過url傳…

代碼隨想錄刷題筆記 DAY 37 | 動態規劃理論基礎 | 斐波那契數 No.509 | 爬樓梯 No.70 | 使用最小花費爬樓梯 No.746

文章目錄 Day 3700. 動態規劃理論基礎01. 斐波那契數&#xff08;No. 509&#xff09;<1> 題目<2> 筆記<3> 代碼 02. 爬樓梯&#xff08;No. 70&#xff09;<1> 題目<2> 筆記<3> 代碼 03. 使用最小花費爬樓梯&#xff08;No. 746&#xff…

ECMAScript-262 @2023版本中的關鍵字和保留字

1、什么是標識符&#xff1f; 所謂標識符&#xff0c;就是javascript里的變量、函數、屬性或函數參數的名稱&#xff0c;可由一個或多個字符組成&#xff0c;當然標識符有命名規范 標識符第一個字符必須是 一個字母、下劃線&#xff08;_&#xff09;或美元符號&#xff08;$…

ONLYOFFICE文檔8.0全新發布:私有部署、卓越安全的協同辦公解決方案

ONLYOFFICE文檔8.0全新發布&#xff1a;私有部署、卓越安全的協同辦公解決方案 文章目錄 ONLYOFFICE文檔8.0全新發布&#xff1a;私有部署、卓越安全的協同辦公解決方案摘要&#x1f4d1;引言 &#x1f31f;正文&#x1f4da;一、ONLYOFFICE文檔概述 &#x1f4ca;二、ONLYOFFI…

【新書推薦】10.2 分支程序設計

稍微復雜一些的程序通常需要做某種條件判斷&#xff0c;然后再決定程序的執行流程。當然也可以無條件跳轉到程序的另一處地址開始執行。本節我們將詳細介紹分支結構的程序設計方法。 針對功能較為復雜的程序&#xff0c;程序開發有一套標準的流程&#xff0c;我們將10.1節中的五…

計算機網絡【網絡安全】

計算機網絡——網絡安全 一、網絡安全問題概述 網絡安全威脅 網絡安全面臨兩大類威脅&#xff0c;被動攻擊和主動攻擊 被動攻擊 指攻擊者從網絡上竊聽他人的通信內容&#xff0c;通常把這類攻擊稱為截獲。 主動攻擊 篡改 攻擊者故意篡改網絡上傳送的報文 惡意程序 拒絕服…

InnoDB索引與優化篇(5)-InnoDB中的查詢優化策略

InnoDB是MySQL數據庫中一種常用的存儲引擎&#xff0c;它具有高性能和可靠性。查詢優化是數據庫開發中非常重要的一環&#xff0c;它能夠幫助我們提高數據庫查詢的效率和性能。在本篇博客中&#xff0c;我們將介紹一些在使用InnoDB存儲引擎時進行查詢優化的常用策略&#xff0c…

貪心 Leetcode 455 分發餅干

分發餅干 Leetcode 455 學習記錄自代碼隨想錄 假設你是一位很棒的家長&#xff0c;想要給你的孩子們一些小餅干。但是&#xff0c;每個孩子最多只能給一塊餅干。 對每個孩子 i&#xff0c;都有一個胃口值 g[i]&#xff0c;這是能讓孩子們滿足胃口的餅干的最小尺寸&#xff1…

神經網絡算法:卷積神經網絡

神經網絡算法&#xff0c;也稱為人工神經網絡算法&#xff0c;是一種模仿人腦神經網絡結構和功能的計算模型。它由多個神經元相互連接而成的網絡組成&#xff0c;每個神經元都有輸入和輸出&#xff0c;并通過學習算法來調整連接權重&#xff0c;從而實現對輸入數據的模式識別和…

JavaScript Web Socket 詳解

Web Socket ? Web Socket&#xff08;套接字&#xff09;的目標是通過一個長時連接實現與服務器全雙工、雙向的通信。在 JavaScript 中創建 Web Socket 時&#xff0c;一個 HTTP 請求會發送到服務器以初始化連接。服務器響應后&#xff0c;連接使用 HTTP 的 Upgrade 頭部從 H…

12、窗口看門狗

目錄 1、窗口看門狗概述 2、常用寄存器和庫函數配置 3、窗口看門狗實驗 1、窗口看門狗概述 之所以稱為窗口就是因為其喂狗時間是一個有上下限的范圍內&#xff08;窗口&#xff09;&#xff0c;你可以通過設定相關寄存器&#xff0c;設定其上限時間&#xff08;下限固定&…

數據結構 棧和隊列 力扣例題AC——代碼以及思路記錄

20. 有效的括號 給定一個只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判斷字符串是否有效。 有效字符串需滿足&#xff1a; 左括號必須用相同類型的右括號閉合。左括號必須以正確的順序閉合。每個右括號都有一個對應…

mysql使用連接池

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、mysql連接池&#xff1f;二、使用步驟1.引入庫 前言 提示&#xff1a;這里可以添加本文要記錄的大概內容&#xff1a; 例如&#xff1a; 提示&#xff1a…

深入理解Flutter中的StreamSubscription和StreamController

在Flutter中&#xff0c;StreamSubscription和StreamController是處理異步數據流的重要工具。它們提供了一種方便的方式來處理來自異步事件源的數據。本文將深入探討它們的區別以及在實際應用中的使用場景。 StreamSubscription StreamSubscription代表了對數據流的訂閱&…

代碼隨想錄算法訓練營番外 刷題日記0301 || 29、兩數相除,31、下一個排列

29、兩數相除 思路&#xff1a;不斷相減就是求解的最直接方法&#xff0c;我這樣計算時間復雜度有點高 // 時間復雜度O(count*divisor) // 空間復雜度O(1)class Solution {int res 0;public int divide(int dividend, int divisor) {// dividend 是被除數if(dividend 0) …

技術棧選型的時候,ruby、go、java、vue、react應該怎么選擇?

選擇適合項目需求、團隊技術背景和偏好、開發速度、性能要求以及可擴展性的技術棧和框架是一個綜合考慮的過程&#xff0c;沒有一種通用的最佳選擇&#xff0c;取決于具體情況。 選擇Vue.js或React應該綜合考慮項目的需求、團隊的技術背景和偏好、生態系統的支持和發展趨勢等因…