溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Tomcat多虛擬主機(jī)配置及原理什么

發(fā)布時(shí)間:2021-12-03 16:20:42 來源:億速云 閱讀:140 作者:柒染 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)Tomcat多虛擬主機(jī)配置及原理什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

我們多數(shù)的Tomcat用戶,對于Tomcat的使用基本使用都是部署應(yīng)用,瀏覽器中進(jìn)行應(yīng)用的請求。而這個對應(yīng)用請求的格式,是這個樣子:

http://localhost:8080/Web

其中8080是Connector對應(yīng)的監(jiān)聽端口,Web是對應(yīng)請求的應(yīng)用,而localhost就是本次的主角,對應(yīng)的就是Tomcat中默認(rèn)包含的一個虛擬主機(jī),對應(yīng)到Tomcat中的Host容器。

在Tomcat的配置文件server.xml中,默認(rèn)包含這樣的配置

Tomcat多虛擬主機(jī)配置及原理什么
默認(rèn)情況下,我們所有的應(yīng)用都部署到了這個虛擬主機(jī)上,所以前面對于應(yīng)用的請求,也就都被Connector轉(zhuǎn)到了localhost這個Host上。

我們再來看虛擬主機(jī)這個概念。其相對于實(shí)體主機(jī),是在一個機(jī)器上虛擬出了多個可供不同站點(diǎn)運(yùn)行的機(jī)制。

在Tomcat中,如果要支持多虛擬主機(jī),配置起來也比較簡單,

  1. 在Engine的組件內(nèi),增加關(guān)于Host的配置信息就可以了。對應(yīng)的各個屬性,可以參考默認(rèn)的localhost主機(jī)。

  2. 在操作系統(tǒng)的hosts文件中,增加你新創(chuàng)建的虛擬主機(jī)名稱對應(yīng)到IP的映射。

  3. 可以選擇在當(dāng)前主機(jī)中增加類似于AccessLog之類的組件。

  4. 重啟Tomcat,使改動生效。

假設(shè)我們新增的虛擬主機(jī)名是remoteHost,此時(shí)在瀏覽器中,我們就可以用

http://remoteHost:port/Webapp

這種形式來訪問應(yīng)用了。

新增虛擬主機(jī)的應(yīng)用部署,可以通過配置主機(jī)的appBase屬性來指定。

當(dāng)然,除以上配置外,在Engine容器上,是可以配置一個defaultHost,也就是在Connector把請求交給Engine后,如果對應(yīng)的Host不能響應(yīng)請求,就會被轉(zhuǎn)到defaultHost來處理。

此時(shí),你可能會發(fā)現(xiàn),多個虛擬主機(jī)之間的應(yīng)用是隔離的,就和我們要搭個網(wǎng)站購買空間一樣,我們只能訪問到自己主機(jī)對應(yīng)的資源與內(nèi)容。這種主機(jī)間應(yīng)用的隔離,在Tomcat內(nèi)是如何實(shí)現(xiàn)的呢?

我們知道,在Tomcat中,整個服務(wù)對外提供,是抽象為Service,在server.xml中對應(yīng)到Service的配置,service的默認(rèn)實(shí)現(xiàn)是StandardService。在實(shí)現(xiàn)中,包含這樣一個Field的聲明:

protected final MapperListener mapperListener =

            new MapperListener(mapper, this);

他本質(zhì)上也相當(dāng)于一個組件,根據(jù)LifeCycle的生命周期進(jìn)行啟動、停止等。以下是其對應(yīng)的類聲明:

public class MapperListener extends LifecycleMBeanBase

        implements ContainerListener, LifecycleListener

在Service的start方法中,也會對MapperListener的start進(jìn)行調(diào)用,在mapperListener啟動過程中,會將自己注冊到Engine的listener中,后續(xù)容器的所有生命周期,都會通知到。這里就是觀察者模式的使用。(參見這里:和Tomcat學(xué)設(shè)計(jì)模式 | 發(fā)布-訂閱模式)

        Engine engine = (Engine) service.getContainer();

        addListeners(engine); // 這里就是注冊


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

            }

        }

我們看到,在啟動時(shí),會將Engine下所有的Host注冊一下。我們來看這里的注冊是在做些啥。

    private void registerHost(Host host) {

        String[] aliases = host.findAliases();

        mapper.addHost(host.getName(), aliases, host);

        for (Container container : host.findChildren()) {

            if (container.getState().isAvailable()) {

                registerContext((Context) container);

            }

        }

    }

這里的mapper,是StandardService中創(chuàng)建的另一個field。這里注冊的Host,以及上面方法中對應(yīng)的registerContext,都被添加到mapper中,用做后面請求處理時(shí)的解析。

這里的addHost,最主要的是做了這樣一個操作

MappedHost[] newHosts = new MappedHost[hosts.length + 1];

        MappedHost newHost = new MappedHost(name, host);

        if (insertMap(hosts, newHosts, newHost)) {

            hosts = newHosts;

 }

后面注冊Context時(shí),方式基本一致。而到了應(yīng)用請求解析時(shí),則是類似下面的流程:(請求處理可以參考:和Tomcat學(xué)設(shè)計(jì)模式 | Facade模式與請求處理,Tomcat是如何處理請求參數(shù)的?)

在Connector將請求傳遞到CoyoteAdaptor時(shí),會在請求頭處理之后,對requestresponse對象做一些后處理,以此傳遞給peipeline,進(jìn)行請求。

在這一過程中,會進(jìn)行這樣的一段處理:

connector.getService().getMapper().map(serverName, decodedURI,

                            version, request.getMappingData());


就會使用到前面為service關(guān)聯(lián)的Mapper,以此根據(jù)request的mappingData進(jìn)行判斷,把請求URI和context建立映射。這個時(shí)候,前面說的注冊的那些東西就要被用到了。

// Virtual host mapping

        MappedHost[] hosts = this.hosts;

        MappedHost mappedHost = exactFindIgnoreCase(hosts, host);

        if (mappedHost == null) {

            if (defaultHostName == null) {

                return;

            }

            mappedHost = exactFind(hosts, defaultHostName);

            if (mappedHost == null) {

                return;

            }

        }

        mappingData.host = mappedHost.object;


        // Context mapping

        ContextList contextList = mappedHost.contextList;

        MappedContext[] contexts = contextList.contexts;

        int pos = find(contexts, uri);

        if (pos == -1) {

            return;

        }

上面幾處標(biāo)紅的地方,hosts就是前面注冊Host時(shí)候變更的對象,defaultHostName是開始時(shí)提到的,為Engine配置的默認(rèn)主機(jī),如果在其它主機(jī)找不到資源時(shí),使用它來響應(yīng)。我們看到,應(yīng)用的mapping,是以Host為基礎(chǔ),從這里再尋找其對應(yīng)的ContextList的。所以不同主機(jī)的應(yīng)用就被隔離開了。

以上,就是Tomcat內(nèi)多虛擬主機(jī)配置,以及其內(nèi)部應(yīng)用隔離和注冊的原理。

  1. 在應(yīng)用部署階段,就會根據(jù)主機(jī)以及之上部署的應(yīng)用進(jìn)行分別register

  2. 在應(yīng)用請求時(shí),再根據(jù)部署時(shí)建立的mapping關(guān)系,去尋找對應(yīng)主機(jī)上的Context

  3. 可以為Engine進(jìn)行defaultHost的配置,在特定主機(jī)上找不到資源時(shí)以此響應(yīng)

關(guān)于Tomcat多虛擬主機(jī)配置及原理什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI