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

資訊專欄INFORMATION COLUMN

聊聊Tomcat的架構設計

cnio / 2526人閱讀

摘要:本篇文章主要是跟大家聊聊的內部架構體系,讓大家對有個整體的認知。方法會創建一個對象,調用它的方法將字節流封裝成對象,在創建組件時,會將組件添加到組件中組件而組件在連接器初始化時就已經創建好了目前為止,只有一個實現類,就是。

微信公眾號「后端進階」,專注后端技術分享:Java、Golang、WEB框架、分布式中間件、服務治理等等。  
老司機傾囊相授,帶你一路進階,來不及解釋了快上車!

Tomcat 是 Java WEB 開發接觸最多的 Servlet 容器,但它不僅僅是一個 Servlet 容器,它還是一個 WEB 應用服務器,在微服務架構體系下,為了降低部署成本,減少資源的開銷,追求的是輕量化與穩定,而 Tomcat 是一個輕量級應用服務器,自然被很多開發人員所接受。

Tomcat 里面藏著很多值得我們每個 Java WEB 開發者學習的知識,可以這么說,當你弄懂了 Tomcat 的設計原理,Java WEB 開發對你來說已經沒有什么秘密可言了。本篇文章主要是跟大家聊聊 Tomcat 的內部架構體系,讓大家對 Tomcat 有個整體的認知。

前面我也說了,Tomcat 的本質其實就是一個 WEB 服務器 + 一個 Servlet 容器,那么它必然需要處理網絡的連接與 Servlet 的管理,因此,Tomcat 設計了兩個核心組件來實現這兩個功能,分別是連接器和容器,連接器用來處理外部網絡連接,容器用來處理內部 Servlet,我用一張圖來表示它們的關系:

一個 Tomcat 代表一個 Server 服務器,一個 Server 服務器可以包含多個 Service 服務,Tomcat 默認的 Service 服務是 Catalina,而一個 Service 服務可以包含多個連接器,因為 Tomcat 支持多種網絡協議,包括 HTTP/1.1、HTTP/2、AJP 等等,一個 Service 服務還會包括一個容器,容器外部會有一層 Engine 引擎所包裹,負責與處理連接器的請求與響應,連接器與容器之間通過 ServletRequest 和 ServletResponse 對象進行交流。

也可以從 server.xml 的配置結構可以看出 tomcat 整體的內部結構:



  

    

    

    

      

        
      
    
  
連接器(Connector)

連接器負責將各種網絡協議封裝起來,對外部屏蔽了網絡連接與 IO 處理的細節,將處理得到的 Request 對象傳遞給容器處理,Tomcat 將處理請求的細節封裝到 ProtocolHandler,ProtocolHandler 是一個接口類型,通過實現 ProtocolHandler 來實現各種協議的處理,如 Http11AprProtocol:

ProtocolHandler 采用組件模式的設計,將處理網絡連接,字節流封裝成 Request 對象,再將 Request 適配成 Servlet 處理 ServletRequest 對象這幾個動作,用組件封裝起來了,ProtocolHandler 包括了三個組件:Endpoint、Processor、Adapter。

Endpoint 在 ProtocolHandler 實現類的構造方法中創建,如下:

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

Endpoint 組件用來處理底層的 Socket 網絡連接,AprEndpoint 里面有個叫 SocketProcessor 的內部類,它負責為 AprEndpoint 將接收到的 Socket 請求轉化成 Request 對象,SocketProcessor 實現了 Runnable 接口,它會有一個專門的線程池來處理,后面我會多帶帶從源碼的角度分析 Endpoint 組件的設計原理。

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

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

process 方法會創建一個 processor 對象,調用它的 process 方法將 Socket 字節流封裝成 Request 對象,在創建 Processor 組件時,會將 Adapter 組件添加到 Processor 組件中:

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

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

  return processor;
}

而 Adapter 組件在連接器初始化時就已經創建好了:

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

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

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

以上連接器的各個組件,我用一張圖說明它們直接的關系:

容器(Container)

在 Tomcat 中一共設計了 4 種容器,它們分別為 Engine、Host、Context、Wrapper,它們的關系如下圖所示:

Engine:表示一個虛擬主機的引擎,一個 Tomcat Server 只有一個 引擎,連接器所有的請求都交給引擎處理,而引擎則會交給相應的虛擬主機去處理請求;

Host:表示虛擬主機,一個容器可以有多個虛擬主機,每個主機都有對應的域名,在 Tomcat 中,一個 webapps 就代表一個虛擬主機,當然 webapps 可以配置多個;

Context:表示一個應用容器,一個虛擬主機可以擁有多個應用,webapps 中每個目錄都代表一個 Context,每個應用可以配置多個 Servlet。

從上圖可看出,各個容器組件之間的關系是由大到小,即父子關系,它們之間關系形成一個樹狀的結構,它們的實現類都實現了 Container 接口,它有如下方法來控制容器組件之間的關系:

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);
}

容器組件之間通過以上幾個方法,即可實現它們之間的父子關系,有沒有發現,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 中有很多組件,組件通過實現 Lifecycle 接口,Tomcat 通過事件機制來實現對這些組件生命周期的管理。

Tomcat 的這種容器設計思想,其實是運用了組合設計模式的思想,組合設計模式最大的優點是可以自由添加節點,這樣也就使得 Tomcat 的容器組件非常地容易進行擴展,符合設計模式中的開閉原則。

現在我們知道了 Tomcat 的容器組件的組合方式,那我們現在就來想一個問題:

當一個請求過來時,Tomcat 是如何識別請求并將它交給特定 Servlet 來處理呢?

從容器的組合關系可以看出,它們調用順序必定是:

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

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

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

我們不妨先從源碼入手:

org.apache.catalina.core.StandardService:

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

Service 實現類中,已經初始化了 Mapper 組件以及它的監聽類 MapperListener,這里先說明一下,在 Tomcat 組件中,標準的實現組件類前綴會有 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 服務啟動的時候,會調用 MapperListener.start() 方法,最終會執行 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);
  }
}

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

定位 Servlet 的流程圖:

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/74716.html

相關文章

  • 聊聊 Nginx 反向代理

    摘要:相信大家都聽說過反向代理,一提到反向代理一定會想到。由于是一款自由的開源的高性能的服務器和反向代理服務器這是個開源的時代啊是一個跨平臺服務器,可以運行在等操作系統上。所以反向代理服務器是引用在服務端。 本文來自于我的慕課網手記:聊聊 Nginx 的反向代理,轉載請保留鏈接 ;) 背景 最近在優化服務基礎設施這塊,正好有時間寫一下Nginx的體會。相信大家都聽說過反向代理,一提到反向代理...

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

    摘要:英文全名為,也叫遠程過程調用,其實就是一個計算機通信協議,它是一種通過網絡從遠程計算機程序上請求服務而不需要了解底層網絡技術的協議。 Hello,Dubbo 你好,dubbo,初次見面,我想和你交個朋友。 Dubbo你到底是什么? 先給出一套官方的說法:Apache Dubbo是一款高性能、輕量級基于Java的RPC開源框架。 那么什么是RPC? 文檔地址:http://dubbo.a...

    evin2016 評論0 收藏0

發表評論

0條評論

cnio

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<