Tomcat工作原理

總體結(jié)構(gòu)

Tomcat 的結(jié)構(gòu)很復(fù)雜,但是 Tomcat 也非常的模塊化,找到了 Tomcat 最核心的模塊,您就抓住了 Tomcat 的“七寸”。下面是 Tomcat 的總體結(jié)構(gòu)圖:

從 上圖中可以看出 Tomcat 的心臟是兩個(gè)組件:Connector 和 Container,關(guān)于這兩個(gè)組件將在后面詳細(xì)介紹。Connector 組件是可以被替換,這樣可以提供給服務(wù)器設(shè)計(jì)者更多的選擇,因?yàn)檫@個(gè)組件是如此重要,不僅跟服務(wù)器的設(shè)計(jì)的本身,而且和不同的應(yīng)用場(chǎng)景也十分相關(guān),所以一 個(gè) Container 可以選擇對(duì)應(yīng)多個(gè) Connector。多個(gè) Connector 和一個(gè) Container 就形成了一個(gè) Service,Service 的概念大家都很熟悉了,有了 Service 就可以對(duì)外提供服務(wù)了,但是 Service 還要一個(gè)生存的環(huán)境,必須要有人能夠給她生命、掌握其生死大權(quán),那就非 Server 莫屬了。所以整個(gè) Tomcat 的生命周期由 Server 控制。

以 Service 作為“婚姻”

我們將 Tomcat 中 Connector、Container 作為一個(gè)整體比作一對(duì)情侶的話,Connector 主要負(fù)責(zé)對(duì)外交流,可以比作為 Boy,Container 主要處理 Connector 接受的請(qǐng)求,主要是處理內(nèi)部事務(wù),可以比作為 Girl。那么這個(gè) Service 就是連接這對(duì)男女的結(jié)婚證了。是 Service 將它們連接在一起,共同組成一個(gè)家庭。當(dāng)然要組成一個(gè)家庭還要很多其它的元素。

說(shuō)白 了,Service 只是在 Connector 和 Container 外面多包一層,把它們組裝在一起,向外面提供服務(wù),一個(gè) Service 可以設(shè)置多個(gè) Connector,但是只能有一個(gè) Container 容器。這個(gè) Service 接口的方法列表如下:

從 Service 接口中定義的方法中可以看出,它主要是為了關(guān)聯(lián) Connector 和 Container,同時(shí)會(huì)初始化它下面的其它組件,注意接口中它并沒(méi)有規(guī)定一定要控制它下面的組件的生命周期。所有組件的生命周期在一個(gè) Lifecycle 的接口中控制,這里用到了一個(gè)重要的設(shè)計(jì)模式,關(guān)于這個(gè)接口將在后面介紹。

Tomcat 中 Service 接口的標(biāo)準(zhǔn)實(shí)現(xiàn)類(lèi)是 StandardService 它不僅實(shí)現(xiàn)了 Service 借口同時(shí)還實(shí)現(xiàn)了 Lifecycle 接口,這樣它就可以控制它下面的組件的生命周期了。StandardService 類(lèi)結(jié)構(gòu)圖如下:

從 上圖中可以看出除了 Service 接口的方法的實(shí)現(xiàn)以及控制組件生命周期的 Lifecycle 接口的實(shí)現(xiàn),還有幾個(gè)方法是用于在事件監(jiān)聽(tīng)的方法的實(shí)現(xiàn),不僅是這個(gè) Service 組件,Tomcat 中其它組件也同樣有這幾個(gè)方法,這也是一個(gè)典型的設(shè)計(jì)模式,將在后面介紹。

下面看一下 StandardService 中主要的幾個(gè)方法實(shí)現(xiàn)的代碼,下面是 setContainer 和 addConnector 方法的源碼:

public void setContainer(Container container) {

????Container oldContainer = this.container;

????if ((oldContainer != null) && (oldContainer instanceof Engine))

????????((Engine) oldContainer).setService(null);

????this.container = container;

????if ((this.container != null) && (this.container instanceof Engine))

????????((Engine) this.container).setService(this);

????if (started && (this.container != null) && (this.container instanceof Lifecycle)) {

????????try {

????????????((Lifecycle) this.container).start();

????????} catch (LifecycleException e) {

????????????;

????????}

????}

????synchronized (connectors) {

????????for (int i = 0; i < connectors.length; i++)

????????????connectors[i].setContainer(this.container);

????}

????if (started && (oldContainer != null) && (oldContainer instanceof Lifecycle)) {

????????try {

????????????((Lifecycle) oldContainer).stop();

????????} catch (LifecycleException e) {

????????????;

????????}

????}

????support.firePropertyChange("container", oldContainer, this.container);

}

這段代碼很簡(jiǎn)單,其實(shí)就是先判斷當(dāng)前的這個(gè) Service 有沒(méi)有已經(jīng)關(guān)聯(lián)了 Container,如果已經(jīng)關(guān)聯(lián)了,那么去掉這個(gè)關(guān)聯(lián)關(guān)系—— oldContainer.setService(null)。如果這個(gè) oldContainer 已經(jīng)被啟動(dòng)了,結(jié)束它的生命周期。然后再替換新的關(guān)聯(lián)、再初始化并開(kāi)始這個(gè)新的 Container 的生命周期。最后將這個(gè)過(guò)程通知感興趣的事件監(jiān)聽(tīng)程序。這里值得注意的地方就是,修改 Container 時(shí)要將新的 Container 關(guān)聯(lián)到每個(gè) Connector,還好 Container 和 Connector 沒(méi)有雙向關(guān)聯(lián),不然這個(gè)關(guān)聯(lián)關(guān)系將會(huì)很難維護(hù)。

public void addConnector(Connector connector) {

????synchronized (connectors) {

????????connector.setContainer(this.container);

????????connector.setService(this);

????????Connector results[] = new Connector[connectors.length + 1];

????????System.arraycopy(connectors, 0, results, 0, connectors.length);

????????results[connectors.length] = connector;

????????connectors = results;

????????if (initialized) {

????????????try {

????????????????connector.initialize();

????????????} catch (LifecycleException e) {

????????????????e.printStackTrace(System.err);

????????????}

????????}

????????if (started && (connector instanceof Lifecycle)) {

????????????try {

????????????????((Lifecycle) connector).start();

????????????} catch (LifecycleException e) {

????????????????;

????????????}

????????}

????????support.firePropertyChange("connector", null, connector);

????}

}

上面是 addConnector 方法,這個(gè)方法也很簡(jiǎn)單,首先是設(shè)置關(guān)聯(lián)關(guān)系,然后是初始化工作,開(kāi)始新的生命周期。這里值得一提的是,注意 Connector 用的是數(shù)組而不是 List 集合,這個(gè)從性能角度考慮可以理解,有趣的是這里用了數(shù)組但是并沒(méi)有向我們平常那樣,一開(kāi)始就分配一個(gè)固定大小的數(shù)組,它這里的實(shí)現(xiàn)機(jī)制是:重新創(chuàng)建一個(gè) 當(dāng)前大小的數(shù)組對(duì)象,然后將原來(lái)的數(shù)組對(duì)象 copy 到新的數(shù)組中,這種方式實(shí)現(xiàn)了類(lèi)似的動(dòng)態(tài)數(shù)組的功能,這種實(shí)現(xiàn)方式,值得我們以后拿來(lái)借鑒。

最新的 Tomcat6 中 StandardService 也基本沒(méi)有變化,但是從 Tomcat5 開(kāi)始 Service、Server 和容器類(lèi)都繼承了 MBeanRegistration 接口,Mbeans 的管理更加合理。