Tomcat源碼分析(零) : 整體架構(gòu)

Tomcat 9.0 源碼

Tomcat架構(gòu)及其重要組件

Tomcat的系統(tǒng)架構(gòu)
Tomcat的系統(tǒng)架構(gòu)
  • Server是管理Service接口的,是Tomcat的一個(gè)頂級容器。管理著多個(gè)Service
  • Service 是服務(wù),管理這一個(gè)Container和多個(gè)Connector,Service的存在依賴于Server
  • Container : 一個(gè)或者多個(gè)Container 可以對應(yīng)一個(gè)Connector,這樣就組成了一個(gè)Service,Service生命周期的由Server進(jìn)行管理。
  • Container和Connector之間的交互媒介是Service,一個(gè)Service可以對應(yīng)多個(gè)Connector,但是只能有一個(gè)Container容器

Server

  • Server 管理著所有的Service。它的主要作用是提供一個(gè)接口可以讓其它程序能夠訪問這個(gè)Service集合,同時(shí)維護(hù)所有service的生命周期等。

Server在Tomcat中的標(biāo)準(zhǔn)實(shí)現(xiàn)是StandardServer。看一下其內(nèi)部的addServiec方法

   @Override
    //FIXME: 它是怎樣調(diào)用起來Service 方法的哪?
    public void addService(Service service) {

        service.setServer(this);
        //同步
        synchronized (servicesLock) {
            
            Service results[] = new Service[services.length + 1];
            System.arraycopy(services, 0, results, 0, services.length);
            results[services.length] = service;
            services = results;

            if (getState().isAvailable()) {
                try {
                    service.start();
                } catch (LifecycleException e) {
                    // Ignore
                }
            }

            // Report this property change to interested listeners
            support.firePropertyChange("service", null, service);
        }

    }

可以看到,在添加Service到Server的時(shí)候,它是將原有數(shù)組的長度加一并將數(shù)組添加到最后。然后啟動(dòng)最新添加的Service

Service

Service 在Tomcat中的標(biāo)準(zhǔn)實(shí)現(xiàn)是StandardService,Service 可以說是一個(gè)標(biāo)準(zhǔn)的服務(wù),擁有獨(dú)立的端口號。
在Service 中可以含有多個(gè)Connector和唯一的一個(gè)Container.這樣的設(shè)計(jì)模式可以允許 例如SSL加密過的請求和沒有經(jīng)過SSL加密的請求在一個(gè)APP中同時(shí)存在

Service 中的setContainer()

   @Override
    public void setContainer(Engine engine) {
        Engine oldEngine = this.engine;
        if (oldEngine != null) {
            // 移除原有Container
            oldEngine.setService(null);
        }
        this.engine = engine;
        if (this.engine != null) {
            this.engine.setService(this);
        }
        if (getState().isAvailable()) {
            if (this.engine != null) {
                try {
                    //開啟Engin
                    this.engine.start();
                } catch (LifecycleException e) {
                    log.warn(sm.getString("standardService.engine.startFailed"), e);
                }
            }
            // Restart MapperListener to pick up new engine.
            try {
                mapperListener.stop();
            } catch (LifecycleException e) {
                log.warn(sm.getString("standardService.mapperListener.stopFailed"), e);
            }
            try {
                mapperListener.start();
            } catch (LifecycleException e) {
                log.warn(sm.getString("standardService.mapperListener.startFailed"), e);
            }
            if (oldEngine != null) {
                try {
                    oldEngine.stop();
                } catch (LifecycleException e) {
                    log.warn(sm.getString("standardService.engine.stopFailed"), e);
                }
            }
        }

        // Report this property change to interested listeners
        support.firePropertyChange("container", oldEngine, this.engine);
    }

Service 的setContainer方法設(shè)置Engine容器,然后啟動(dòng)這個(gè)容器,并將原有的容器的停止掉。Service 的setConnector幾乎是同樣的套路

Container

Container 由四個(gè)子容器組成:

  • Engine : 表示整個(gè)Catalina Servlet引擎,是Container 只用最高層,用來管理Host 或者Context的實(shí)現(xiàn)
  • 如果你想攔截每一個(gè)到Servlet的請求,可以通過
  • Host :表示一個(gè)Engine管理下的一個(gè)虛擬主機(jī),比如你訪問的Localhost就是一個(gè)虛擬主機(jī)。作用是運(yùn)行多個(gè)應(yīng)用
    其處理過程可以總結(jié)如下:
    1. 為特定的請求URL選擇一個(gè)Context容器
    2. 把Context容器綁定到線程中
    3. 判斷是否是一個(gè)異步請求
    4. 讓Context去處理這個(gè)請求
    5. Context執(zhí)行invoke方法,進(jìn)入管道中,由StandardContextValve(是ContextValve的標(biāo)準(zhǔn)實(shí)現(xiàn)類)處理
  • Context:Context 是用來管理Servlet的容器,Context就對應(yīng)一個(gè)應(yīng)用。所以我們部署應(yīng)用時(shí)需要?jiǎng)?chuàng)建一個(gè)Context容器,Context負(fù)責(zé)管理Wrapper.
  • Wrapper : 用來管理一個(gè)Servlet的生命周期

Connector

Connector 是Tomcat的連接器,主要任務(wù)是負(fù)責(zé)處理瀏覽器發(fā)送過來的請求,并創(chuàng)建一個(gè)Request和Response對象,用于和前端Client交換數(shù)據(jù),然后產(chǎn)生一個(gè)線程,并將Request對象和Response對象傳遞給線程,后面對這兩個(gè)線程的處理就是Container的事情了

  1. 實(shí)例化Connector,構(gòu)造一個(gè)Connector對象
  2. 調(diào)用Connector的initIntenal方法,初始化Connetor
  3. 調(diào)用ProtocolHanlder的init方法,完成ProtocolHanlder的初始化。這個(gè)過程包括了創(chuàng)建線程池并創(chuàng)建一個(gè)線程處理瀏覽器請求
  4. 調(diào)用Connector的startIntenal方法,啟動(dòng)Connector
  5. 調(diào)用ProtocolHandler的start方法,啟動(dòng)Protocolhanlder
  6. 調(diào)用MapperListener的start方法,啟動(dòng)監(jiān)聽器程序

不同于Container ,Connector是一個(gè)實(shí)現(xiàn)類.其相當(dāng)于一個(gè)容器處理基于Http的請求
CoyoteAdapter,是connector和container的橋梁,經(jīng)過這一步,請求就從connector傳遞到container中里了。Adapter

要注意的是:最先處理請求的Request是org.apache.coyote.Request類型,這是一個(gè)Tomcat中一個(gè)輕量級對象,完成基本的請求處理后很容易被JVM回收,那為什么不直接交給Connector.Request對象處理呢?由于后者是Servlet容器真正傳遞的對象其完成的職責(zé)比前者復(fù)雜,這里使用org.apache.coyote.Request主要減輕后者的任務(wù)負(fù)擔(dān),出于性能考慮才這么設(shè)計(jì)。

從connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);這句代碼中可以知道下一步的處理需要交給Container容器了。

Context容器和Wrapper

  • Wrapper 接口是Context的抽象接口

  • Context的啟動(dòng):

  • Context的啟動(dòng)過程就是加載整個(gè)類資源文件和打開子容器,以及pipeline的過程。

  • StandardContextValve的invoke 方法會(huì)通過request得到相應(yīng)的ContextWrapper,在這個(gè)過程中如果沒有發(fā)生異常,服務(wù)端會(huì)向client 發(fā)送一個(gè)ack響應(yīng)

  • StandardContext的處理流程可以用下面的圖來簡化:

  • StandardContext的addServlet會(huì)添加一個(gè)Servlet類,并通過Servlet名字分配一個(gè)ServletWrppar,如果沒有則為其新建一個(gè)。通過這個(gè)Wrappar來管理這個(gè)Servlet。。
  • Wrapper與Servlet息息相關(guān),其中的loadServlet負(fù)責(zé)裝載Servlet.Wrapper是最底層
  • Standard類主要負(fù)責(zé)初始化一個(gè)Servlet實(shí)例,并調(diào)用該實(shí)例的init方法,然后通知感興趣的事件監(jiān)聽程序。用了Wrapper的invoke方法,這個(gè)方法完成什么呢?

附錄: 一個(gè)HTTP請求是怎樣通過Tomcat到你的應(yīng)用中的

Http請求在Container中的傳遞流程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容