您好,登錄后才能下訂單哦!
本篇內容主要講解“中間件容器的實現原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“中間件容器的實現原理是什么”吧!
Tomcat 的結構很復雜,但是Tomcat也非常的模塊化,找到了Tomcat 最核心的模塊,就抓住Tomcat的“七寸”。
Tomcat的總體結構從外到內進行分布,最大范圍的服務容器是Server組件,Service服務組件(可以有多個同時存在),Connector(連接器)、Container(容器服務),其他組件:Jasper(Jasper解析)、Naming(命名服務)、Session(會話管理)、Logging(日志管理)、JMX(Java 管理器擴展服務)、Websocket(交互服務)。
從上圖中可以看出 Tomcat 的心臟是兩個組件:Connector 和 Container,關于這兩個組件將在后面詳細介紹。
Connector 組件是可以被替換,這樣可以提供給服務器設計者更多的選擇,因為這個組件是如此重要,不僅跟服務器的設計的本身,而且和不同的應用場景也十分相關,所以一個 Container 可以選擇對應多個 Connector。 多個 Connector 和一個 Container 就形成了一個 Service。
Service的概念大家都很熟悉了,有了 Service 就可以對外提供服務了,但是 Service 還要一個生存的環境,必須要有人能夠給她生命、掌握其生死大權,那就非 Server 莫屬了。所以整個 Tomcat 的生命周期由Server 控制。
我們將 Tomcat 中 Connector、Container 作為一個整體比作一對情 侶的話,Connector 主要負責對外交流,可以比作為Boy,Container 主要處理 Connector 接受的請求,主要是處理內部事務,可以比作 為 Girl。那么這個 Service 就是連接這對男女的結婚證了。是 Service 將它們連接在一起,共同組成一個家庭。當然要組成一個家 庭還要很多其它的元素。
說白了,Service 只是在 Connector 和 Container 外面多包一層, 把它們組裝在一起,向外面提供服務,一個 Service 可以設置多個 Connector,但是只能有一個 Container 容器。這個 Service 接口的 方法列表如下:
從 Service 接口中定義的方法中可以看出,它主要是為了關聯Connector 和 Container,同時會初始化它下面的其它組件,注意接口中它并沒有規定一定要控制它下面的組件的生命周期。所有組件的生命周期在一個 Lifecycle 的接口中控制,這里用到了一個重要的設計模式,關于這個接口將在后面介紹。
Tomcat 中 Service 接口的標準實現類是 StandardService 它不僅 實現了 Service 借口同時還實現了 Lifecycle 接口,這樣它就可以控制它下面的組件的生命周期了。StandardService 類結構圖如下
從上圖中可以看出除了 Service 接口的方法的實現以及控制組件生命周期的 Lifecycle 接口的實現,還有幾個方法是用于在事件監聽的方法的實現,不僅是這個 Service 組件,Tomcat中其它組件也同樣有這幾個方法,這也是一個典型的設計模式,將在后面介紹。
下面看一下 StandardService 中主要的幾個方法實現的代碼,下面是 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); }
這段代碼很簡單,其實就是先判斷當前的這個 Service 有沒有已經關聯了 Container,如果已經關聯了,那么去掉這個關聯關系——oldContainer.setService(null)。如果這個 oldContainer 已經被啟動了,結束它的生命周期。然后再替換新的關聯、再初始化并開始這個新的 Container 的生命周期。最后將這個過程通知感興趣的事件監 聽程序。這里值得注意的地方就是,修改 Container 時要將新的Container 關聯到每個 Connector,還好 Container 和 Connector 沒有雙向關聯,不然這個關聯關系將會很難維護。
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 方法,這個方法也很簡單,首先是設置關聯關系,然后是初始化工作,開始新的生命周期。這里值得一提的是,注意 Connector 用的是數組而不是 List 集合,這個從性能角度考慮可以理解,有趣的是這里用了數組但是并沒有向我們平常那樣,一開始就分配一個固定大小的數組,它這里的實現機制是:重新創建一個當前大小的數組對象,然后將原來的數組對象 copy 到新的數組中,這種方式實現了類似的動態數組的功能,這種實現方式,值得我們以后拿來借鑒。
最新的 Tomcat6 中 StandardService 也基本沒有變化,但是從Tomcat5 開始 Service、Server 和容器類都繼承了MBeanRegistration 接口,Mbeans 的管理更加合理。
前面說一對情侶因為 Service 而成為一對夫妻,有了能夠組成一個家庭的基本條件,但是它們還要有個實體的家,這是它們在社會上生存之本,有了家它們就可以安心的為人民服務了,一起為社會創造財富。
Server 要完成的任務很簡單,就是要能夠提供一個接口讓其它程序能夠訪問到這個 Service 集合、同時要維護它所包含的所有 Service 的生命周期,包括如何初始化、如何結束服務、如何找到別人要訪問的 Service。
還有其它的一些次要的任務,如您住在這個地方去登記啊、可能還有要配合當地機關日常的安全檢查什么 的。
Server 的類結構圖如下:
它的標準實現類 StandardServer 實現了上面這些方法,同時也實現Lifecycle、MbeanRegistration 兩個接口的所有方法,下面主要看一下 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 是相互關聯的,Server也是和 Service 管理 Connector 一樣管理它,也是將 Service 放在一個數組中,后面部分的代碼也是管理這個新加進來的 Service 的生命周期。Tomcat6 中也是沒有什么變化的。
前面一直在說 Service 和 Server 管理它下面組件的生命周期,那它們是如何管理的呢?
Tomcat 中組件的生命周期是通過 Lifecycle 接口來控制的,組件只要繼承這個接口并實現其中的方法就可以統一被擁有它的組件控制了,這樣一層一層的直到一個最高級的組件就可以控制 Tomcat 中所有組件的生命周期,這個最高的組件就是 Server,而控制 Server 的是 Startup,也就是您啟動和關閉 Tomcat。
下面是 Lifecycle 接口的類結構圖:
除了控制生命周期的 Start 和 Stop 方法外還有一個監聽機制,在生命周期開始和結束的時候做一些額外的操作。這個機制在其它的框架中也被使用,如在 Spring 中。關于這個設計模式會在后面介紹。
Lifecycle 接口的方法的實現都在其它組件中,就像前面中說的,組件的生命周期由包含它的父組件控制,所以它的 Start 方法自然就是調用它下面的組件的 Start 方法,Stop 方法也是一樣。如在 Server 中 Start 方法就會調用 Service 組件的 Start 方法,Server 的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); }
監聽的代碼會包圍 Service 組件的啟動過程,就是簡單的循環啟動所有 Service 組件的Start方法,但是所有 Service 必須要實現Lifecycle 接口,這樣做會更加靈活。 Server 的 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 方法差不多。
到此,相信大家對“中間件容器的實現原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。