溫馨提示×

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

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

中間件容器的實(shí)現(xiàn)原理是什么

發(fā)布時(shí)間:2021-10-13 16:00:18 來源:億速云 閱讀:106 作者:iii 欄目:編程語言

本篇內(nèi)容主要講解“中間件容器的實(shí)現(xiàn)原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“中間件容器的實(shí)現(xiàn)原理是什么”吧!

Tomcat系統(tǒng)架構(gòu)分析

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

Tomcat 整體結(jié)構(gòu)

Tomcat的總體結(jié)構(gòu)從外到內(nèi)進(jìn)行分布,最大范圍的服務(wù)容器是Server組件,Service服務(wù)組件(可以有多個(gè)同時(shí)存在),Connector(連接器)、Container(容器服務(wù)),其他組件:Jasper(Jasper解析)、Naming(命名服務(wù))、Session(會(huì)話管理)、Logging(日志管理)、JMX(Java 管理器擴(kuò)展服務(wù))、Websocket(交互服務(wù))。

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

中間件容器的實(shí)現(xiàn)原理是什么

從上圖中可以看出 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è)家 庭還要很多其它的元素。

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


1) Service 接口

方法列表

中間件容器的實(shí)現(xiàn)原理是什么

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

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

2) StandardService 的類結(jié)構(gòu)圖

方法列表

中間件容器的實(shí)現(xiàn)原理是什么

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

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

3) StandardService. SetContainer
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 有沒有已經(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)、再初始化并開始這個(gè)新的 Container 的生命周期。最后將這個(gè)過程通知感興趣的事件監(jiān) 聽程序。這里值得注意的地方就是,修改 Container 時(shí)要將新的Container 關(guān)聯(lián)到每個(gè) Connector,還好 Container 和 Connector 沒有雙向關(guān)聯(lián),不然這個(gè)關(guān)聯(lián)關(guān)系將會(huì)很難維護(hù)。

4) StandardService. addConnector
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)系,然后是初始化工作,開始新的生命周期。這里值得一提的是,注意 Connector 用的是數(shù)組而不是 List 集合,這個(gè)從性能角度考慮可以理解,有趣的是這里用了數(shù)組但是并沒有向我們平常那樣,一開始就分配一個(gè)固定大小的數(shù)組,它這里的實(shí)現(xiàn)機(jī)制是:重新創(chuàng)建一個(gè)當(dāng)前大小的數(shù)組對(duì)象,然后將原來的數(shù)組對(duì)象 copy 到新的數(shù)組中,這種方式實(shí)現(xiàn)了類似的動(dòng)態(tài)數(shù)組的功能,這種實(shí)現(xiàn)方式,值得我們以后拿來借鑒。


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

以 Server 為“居”

前面說一對(duì)情侶因?yàn)?Service 而成為一對(duì)夫妻,有了能夠組成一個(gè)家庭的基本條件,但是它們還要有個(gè)實(shí)體的家,這是它們?cè)谏鐣?huì)上生存之本,有了家它們就可以安心的為人民服務(wù)了,一起為社會(huì)創(chuàng)造財(cái)富。

Server 要完成的任務(wù)很簡(jiǎn)單,就是要能夠提供一個(gè)接口讓其它程序能夠訪問到這個(gè) Service 集合、同時(shí)要維護(hù)它所包含的所有 Service 的生命周期,包括如何初始化、如何結(jié)束服務(wù)、如何找到別人要訪問的 Service。

還有其它的一些次要的任務(wù),如您住在這個(gè)地方去登記啊、可能還有要配合當(dāng)?shù)貦C(jī)關(guān)日常的安全檢查什么 的。

Server 的類結(jié)構(gòu)圖如下:

1) Server 的類結(jié)構(gòu)圖

中間件容器的實(shí)現(xiàn)原理是什么


它的標(biāo)準(zhǔn)實(shí)現(xiàn)類 StandardServer 實(shí)現(xiàn)了上面這些方法,同時(shí)也實(shí)現(xiàn)Lifecycle、MbeanRegistration 兩個(gè)接口的所有方法,下面主要看一下 StandardServer 重要的一個(gè)方法 addService 的實(shí)現(xiàn):

2) StandardServer.addService
public void addService(Service service) {
 	service.setServer(this);
 	synchronized (services) {
 	Service results[] = new Service[services.length + 1];
 	System.arraycopy(services, 0, results, 0, services.length);
 	results[services.length] = service;
 	services = results;
 		if (initialized) {
			 try {
			 service.initialize();
			 } catch (LifecycleException e) {
			 e.printStackTrace(System.err);
			 }
		}
		 if (started && (service instanceof Lifecycle)) {
					 try {
					 ((Lifecycle) service).start();
					 } catch (LifecycleException e) {
					 ;
					 }
 		}
 		support.firePropertyChange("service", null, service);
 }
}

從上面第一句就知道了 Service 和 Server 是相互關(guān)聯(lián)的,Server也是和 Service 管理 Connector 一樣管理它,也是將 Service 放在一個(gè)數(shù)組中,后面部分的代碼也是管理這個(gè)新加進(jìn)來的 Service 的生命周期。Tomcat6 中也是沒有什么變化的。


組件的生命線“Lifecycle”
 前面一直在說 Service 和 Server 管理它下面組件的生命周期,那它們是如何管理的呢?

Tomcat 中組件的生命周期是通過 Lifecycle 接口來控制的,組件只要繼承這個(gè)接口并實(shí)現(xiàn)其中的方法就可以統(tǒng)一被擁有它的組件控制了,這樣一層一層的直到一個(gè)最高級(jí)的組件就可以控制 Tomcat 中所有組件的生命周期,這個(gè)最高的組件就是 Server,而控制 Server 的是 Startup,也就是您啟動(dòng)和關(guān)閉 Tomcat。

下面是 Lifecycle 接口的類結(jié)構(gòu)圖:

1) Lifecycle 類結(jié)構(gòu)圖

中間件容器的實(shí)現(xiàn)原理是什么

除了控制生命周期的 Start 和 Stop 方法外還有一個(gè)監(jiān)聽機(jī)制,在生命周期開始和結(jié)束的時(shí)候做一些額外的操作。這個(gè)機(jī)制在其它的框架中也被使用,如在 Spring 中。關(guān)于這個(gè)設(shè)計(jì)模式會(huì)在后面介紹。

Lifecycle 接口的方法的實(shí)現(xiàn)都在其它組件中,就像前面中說的,組件的生命周期由包含它的父組件控制,所以它的 Start 方法自然就是調(diào)用它下面的組件的 Start 方法,Stop 方法也是一樣。如在 Server 中 Start 方法就會(huì)調(diào)用 Service 組件的 Start 方法,Server 的Start 方法代碼如下:

2) StandardServer.Start
public void start() throws LifecycleException {
 	if (started) {
 	      log.debug(sm.getString("standardServer.start.started"));
              return;
 	}
 	lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
 	lifecycle.fireLifecycleEvent(START_EVENT, null);
 	started = true;
 	synchronized (services) {
 		for (int i = 0; i < services.length; i++) {
 			if (services[i] instanceof Lifecycle)
 				((Lifecycle) services[i]).start();
 			}
 		}
 	lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}

監(jiān)聽的代碼會(huì)包圍 Service 組件的啟動(dòng)過程,就是簡(jiǎn)單的循環(huán)啟動(dòng)所有 Service 組件的Start方法,但是所有 Service 必須要實(shí)現(xiàn)Lifecycle 接口,這樣做會(huì)更加靈活。 Server 的 Stop 方法代碼如下:

3) StandardServer.Stop
public void stop() throws LifecycleException {
 	if (!started)
 		return;
 	lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
 	lifecycle.fireLifecycleEvent(STOP_EVENT, null);
 	started = false;
 	for (int i = 0; i < services.length; i++) {
 		if (services[i] instanceof Lifecycle)
 			((Lifecycle) services[i]).stop();
 		}
 		lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
}

它所要做的事情也和 Start 方法差不多。

到此,相信大家對(duì)“中間件容器的實(shí)現(xiàn)原理是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

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

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

AI