国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

聊聊Tomcat的架構(gòu)設(shè)計(jì)

cnio / 2523人閱讀

摘要:本篇文章主要是跟大家聊聊的內(nèi)部架構(gòu)體系,讓大家對(duì)有個(gè)整體的認(rèn)知。方法會(huì)創(chuàng)建一個(gè)對(duì)象,調(diào)用它的方法將字節(jié)流封裝成對(duì)象,在創(chuàng)建組件時(shí),會(huì)將組件添加到組件中組件而組件在連接器初始化時(shí)就已經(jīng)創(chuàng)建好了目前為止,只有一個(gè)實(shí)現(xiàn)類,就是。

微信公眾號(hào)「后端進(jìn)階」,專注后端技術(shù)分享:Java、Golang、WEB框架、分布式中間件、服務(wù)治理等等。  
老司機(jī)傾囊相授,帶你一路進(jìn)階,來(lái)不及解釋了快上車!

Tomcat 是 Java WEB 開(kāi)發(fā)接觸最多的 Servlet 容器,但它不僅僅是一個(gè) Servlet 容器,它還是一個(gè) WEB 應(yīng)用服務(wù)器,在微服務(wù)架構(gòu)體系下,為了降低部署成本,減少資源的開(kāi)銷,追求的是輕量化與穩(wěn)定,而 Tomcat 是一個(gè)輕量級(jí)應(yīng)用服務(wù)器,自然被很多開(kāi)發(fā)人員所接受。

Tomcat 里面藏著很多值得我們每個(gè) Java WEB 開(kāi)發(fā)者學(xué)習(xí)的知識(shí),可以這么說(shuō),當(dāng)你弄懂了 Tomcat 的設(shè)計(jì)原理,Java WEB 開(kāi)發(fā)對(duì)你來(lái)說(shuō)已經(jīng)沒(méi)有什么秘密可言了。本篇文章主要是跟大家聊聊 Tomcat 的內(nèi)部架構(gòu)體系,讓大家對(duì) Tomcat 有個(gè)整體的認(rèn)知。

前面我也說(shuō)了,Tomcat 的本質(zhì)其實(shí)就是一個(gè) WEB 服務(wù)器 + 一個(gè) Servlet 容器,那么它必然需要處理網(wǎng)絡(luò)的連接與 Servlet 的管理,因此,Tomcat 設(shè)計(jì)了兩個(gè)核心組件來(lái)實(shí)現(xiàn)這兩個(gè)功能,分別是連接器和容器,連接器用來(lái)處理外部網(wǎng)絡(luò)連接,容器用來(lái)處理內(nèi)部 Servlet,我用一張圖來(lái)表示它們的關(guān)系:

一個(gè) Tomcat 代表一個(gè) Server 服務(wù)器,一個(gè) Server 服務(wù)器可以包含多個(gè) Service 服務(wù),Tomcat 默認(rèn)的 Service 服務(wù)是 Catalina,而一個(gè) Service 服務(wù)可以包含多個(gè)連接器,因?yàn)?Tomcat 支持多種網(wǎng)絡(luò)協(xié)議,包括 HTTP/1.1、HTTP/2、AJP 等等,一個(gè) Service 服務(wù)還會(huì)包括一個(gè)容器,容器外部會(huì)有一層 Engine 引擎所包裹,負(fù)責(zé)與處理連接器的請(qǐng)求與響應(yīng),連接器與容器之間通過(guò) ServletRequest 和 ServletResponse 對(duì)象進(jìn)行交流。

也可以從 server.xml 的配置結(jié)構(gòu)可以看出 tomcat 整體的內(nèi)部結(jié)構(gòu):



  

    

    

    

      

        
      
    
  
連接器(Connector)

連接器負(fù)責(zé)將各種網(wǎng)絡(luò)協(xié)議封裝起來(lái),對(duì)外部屏蔽了網(wǎng)絡(luò)連接與 IO 處理的細(xì)節(jié),將處理得到的 Request 對(duì)象傳遞給容器處理,Tomcat 將處理請(qǐng)求的細(xì)節(jié)封裝到 ProtocolHandler,ProtocolHandler 是一個(gè)接口類型,通過(guò)實(shí)現(xiàn) ProtocolHandler 來(lái)實(shí)現(xiàn)各種協(xié)議的處理,如 Http11AprProtocol:

ProtocolHandler 采用組件模式的設(shè)計(jì),將處理網(wǎng)絡(luò)連接,字節(jié)流封裝成 Request 對(duì)象,再將 Request 適配成 Servlet 處理 ServletRequest 對(duì)象這幾個(gè)動(dòng)作,用組件封裝起來(lái)了,ProtocolHandler 包括了三個(gè)組件:Endpoint、Processor、Adapter。

Endpoint 在 ProtocolHandler 實(shí)現(xiàn)類的構(gòu)造方法中創(chuàng)建,如下:

public Http11AprProtocol() {
  super(new AprEndpoint());
}

Endpoint 組件用來(lái)處理底層的 Socket 網(wǎng)絡(luò)連接,AprEndpoint 里面有個(gè)叫 SocketProcessor 的內(nèi)部類,它負(fù)責(zé)為 AprEndpoint 將接收到的 Socket 請(qǐng)求轉(zhuǎn)化成 Request 對(duì)象,SocketProcessor 實(shí)現(xiàn)了 Runnable 接口,它會(huì)有一個(gè)專門(mén)的線程池來(lái)處理,后面我會(huì)多帶帶從源碼的角度分析 Endpoint 組件的設(shè)計(jì)原理。

org.apache.tomcat.util.net.AprEndpoint.SocketProcessor#doRun:

// Process the request from this socket
SocketState state = getHandler().process(socketWrapper, event);

process 方法會(huì)創(chuàng)建一個(gè) processor 對(duì)象,調(diào)用它的 process 方法將 Socket 字節(jié)流封裝成 Request 對(duì)象,在創(chuàng)建 Processor 組件時(shí),會(huì)將 Adapter 組件添加到 Processor 組件中:

org.apache.coyote.http11.AbstractHttp11Protocol#createProcessor:

protected Processor createProcessor() {
  Http11Processor processor = new Http11Processor();
  // set Adapter 組件
  processor.setAdapter(getAdapter());

  return processor;
}

而 Adapter 組件在連接器初始化時(shí)就已經(jīng)創(chuàng)建好了:

org.apache.catalina.connector.Connector#initInternal:

// Initialize adapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);

目前為止,Tomcat 只有一個(gè) Adapter 實(shí)現(xiàn)類,就是 CoyoteAdapter。Adapter 的主要作用是將 Request 對(duì)象適配成容器能夠識(shí)別的 Request 對(duì)象,比如 Servlet 容器,它的只能識(shí)別 ServletRequest 對(duì)象,這時(shí)候就需要 Adapter 適配器類作一層適配。

以上連接器的各個(gè)組件,我用一張圖說(shuō)明它們直接的關(guān)系:

容器(Container)

在 Tomcat 中一共設(shè)計(jì)了 4 種容器,它們分別為 Engine、Host、Context、Wrapper,它們的關(guān)系如下圖所示:

Engine:表示一個(gè)虛擬主機(jī)的引擎,一個(gè) Tomcat Server 只有一個(gè) 引擎,連接器所有的請(qǐng)求都交給引擎處理,而引擎則會(huì)交給相應(yīng)的虛擬主機(jī)去處理請(qǐng)求;

Host:表示虛擬主機(jī),一個(gè)容器可以有多個(gè)虛擬主機(jī),每個(gè)主機(jī)都有對(duì)應(yīng)的域名,在 Tomcat 中,一個(gè) webapps 就代表一個(gè)虛擬主機(jī),當(dāng)然 webapps 可以配置多個(gè);

Context:表示一個(gè)應(yīng)用容器,一個(gè)虛擬主機(jī)可以擁有多個(gè)應(yīng)用,webapps 中每個(gè)目錄都代表一個(gè) Context,每個(gè)應(yīng)用可以配置多個(gè) Servlet。

從上圖可看出,各個(gè)容器組件之間的關(guān)系是由大到小,即父子關(guān)系,它們之間關(guān)系形成一個(gè)樹(shù)狀的結(jié)構(gòu),它們的實(shí)現(xiàn)類都實(shí)現(xiàn)了 Container 接口,它有如下方法來(lái)控制容器組件之間的關(guān)系:

public interface Container extends Lifecycle {
  Container getParent();
  void setParent(Container container);
  void addChild(Container child);
  Container findChild(String name);
  Container[] findChildren();
  void removeChild(Container child);
}

容器組件之間通過(guò)以上幾個(gè)方法,即可實(shí)現(xiàn)它們之間的父子關(guān)系,有沒(méi)有發(fā)現(xiàn),Container 接口還繼承了 Lifecycle 接口,它有如下方法:

public interface Lifecycle {   
  public static final String INIT_EVENT = "init";  
  public static final String START_EVENT = "start";   
  public static final String BEFORE_START_EVENT = "before_start";   
  public static final String AFTER_START_EVENT = "after_start";   
  public static final String STOP_EVENT = "stop";   
  public static final String BEFORE_STOP_EVENT = "before_stop";   
  public static final String AFTER_STOP_EVENT = "after_stop";   
  public static final String DESTROY_EVENT = "destroy";  

  public void addLifecycleListener(LifecycleListener listener);   
  public LifecycleListener[] findLifecycleListeners();   
  public void removeLifecycleListener(LifecycleListener listener);   
  public void start() throws LifecycleException;   
  public void stop() throws LifecycleException;   
}  

Tomcat 中有很多組件,組件通過(guò)實(shí)現(xiàn) Lifecycle 接口,Tomcat 通過(guò)事件機(jī)制來(lái)實(shí)現(xiàn)對(duì)這些組件生命周期的管理。

Tomcat 的這種容器設(shè)計(jì)思想,其實(shí)是運(yùn)用了組合設(shè)計(jì)模式的思想,組合設(shè)計(jì)模式最大的優(yōu)點(diǎn)是可以自由添加節(jié)點(diǎn),這樣也就使得 Tomcat 的容器組件非常地容易進(jìn)行擴(kuò)展,符合設(shè)計(jì)模式中的開(kāi)閉原則。

現(xiàn)在我們知道了 Tomcat 的容器組件的組合方式,那我們現(xiàn)在就來(lái)想一個(gè)問(wèn)題:

當(dāng)一個(gè)請(qǐng)求過(guò)來(lái)時(shí),Tomcat 是如何識(shí)別請(qǐng)求并將它交給特定 Servlet 來(lái)處理呢?

從容器的組合關(guān)系可以看出,它們調(diào)用順序必定是:

Engine -> Host -> Context -> Wrapper -> Servlet

那么 Tomcat 是如何來(lái)定位 Servlet 的呢?答案是利用 Mapper 組件來(lái)完成定位的工作。

Mapper 最主要的核心功能是保存容器組件之間訪問(wèn)路徑的映射關(guān)系,它是如何做到這點(diǎn)的呢?

我們不妨先從源碼入手:

org.apache.catalina.core.StandardService:

protected final Mapper mapper = new Mapper();
protected final MapperListener mapperListener = new MapperListener(this);

Service 實(shí)現(xiàn)類中,已經(jīng)初始化了 Mapper 組件以及它的監(jiān)聽(tīng)類 MapperListener,這里先說(shuō)明一下,在 Tomcat 組件中,標(biāo)準(zhǔn)的實(shí)現(xiàn)組件類前綴會(huì)有 Standard,比如:

org.apache.catalina.core.StandardServer
org.apache.catalina.core.StandardService
org.apache.catalina.core.StandardEngine
org.apache.catalina.core.StandardHost
org.apache.catalina.core.StandardContext
org.apache.catalina.core.StandardWrapperz

在 Service 服務(wù)啟動(dòng)的時(shí)候,會(huì)調(diào)用 MapperListener.start() 方法,最終會(huì)執(zhí)行 MapperListener 的 startInternal 方法:

org.apache.catalina.mapper.MapperListener#startInternal:

Container[] conHosts = engine.findChildren();
for (Container conHost : conHosts) {
  Host host = (Host) conHost;
  if (!LifecycleState.NEW.equals(host.getState())) {
    // Registering the host will register the context and wrappers
    registerHost(host);
  }
}

該方法會(huì)注冊(cè)新的虛擬主機(jī),接著 registerHost() 方法會(huì)注冊(cè) context,以此類推,從而將容器組件直接的訪問(wèn)的路徑都注冊(cè)到 Mapper 中。

定位 Servlet 的流程圖:

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/74716.html

相關(guān)文章

  • 聊聊 Nginx 反向代理

    摘要:相信大家都聽(tīng)說(shuō)過(guò)反向代理,一提到反向代理一定會(huì)想到。由于是一款自由的開(kāi)源的高性能的服務(wù)器和反向代理服務(wù)器這是個(gè)開(kāi)源的時(shí)代啊是一個(gè)跨平臺(tái)服務(wù)器,可以運(yùn)行在等操作系統(tǒng)上。所以反向代理服務(wù)器是引用在服務(wù)端。 本文來(lái)自于我的慕課網(wǎng)手記:聊聊 Nginx 的反向代理,轉(zhuǎn)載請(qǐng)保留鏈接 ;) 背景 最近在優(yōu)化服務(wù)基礎(chǔ)設(shè)施這塊,正好有時(shí)間寫(xiě)一下Nginx的體會(huì)。相信大家都聽(tīng)說(shuō)過(guò)反向代理,一提到反向代理...

    NikoManiac 評(píng)論0 收藏0
  • dubbo源碼解析(一)Hello,Dubbo

    摘要:英文全名為,也叫遠(yuǎn)程過(guò)程調(diào)用,其實(shí)就是一個(gè)計(jì)算機(jī)通信協(xié)議,它是一種通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù)而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。 Hello,Dubbo 你好,dubbo,初次見(jiàn)面,我想和你交個(gè)朋友。 Dubbo你到底是什么? 先給出一套官方的說(shuō)法:Apache Dubbo是一款高性能、輕量級(jí)基于Java的RPC開(kāi)源框架。 那么什么是RPC? 文檔地址:http://dubbo.a...

    evin2016 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<