2010-12-22 50 views
11

我知道一個servlet容器(如Apache Tomcat)運行在JVM的單個實例中,這意味着它的所有servlet都將在同一個進程中運行。Servlet容器是否阻止Web應用程序引起彼此干擾,以及它們如何執行?

我也知道servlet容器的體系結構意味着每個web應用程序都存在於它自己的上下文中,這表明它與其他web應用程序是隔離的。

如這裏所描繪的: alt text

接受每一個web應用程序是孤立的,我希望你可以創建一個相同的Web應用程序的2份,改變各的名稱和上下文路徑(以及任何其他相關配置),並行運行它們,而不會影響另一個。 this question的答案似乎支持這種觀點。

但是,一位同事根據他們嘗試這種做法的經驗不同意。

他們採用了一個web應用程序,並試圖在同一個servlet容器中運行兩個單獨的實例(使用不同的名稱等),並遇到兩個實例衝突的問題(我無法詳細說明,因爲我沒有參與那工作)。

基於此,他們認爲,由於Web應用程序在相同的進程空間中運行,因此它們不能被隔離,並且諸如類屬性之類的事情最終會被無意中共享。 This answer似乎表明同樣的事情

的兩種觀點似乎並不兼容,所以我問你: 做servlet容器防止相互衝突部署到同一容器中的Web應用程序?

If yes他們是怎麼做到的?

如果,干擾爲什麼會發生?

最後,在什麼情況下可以分離Web應用程序衝突並導致彼此干擾?,可能涉及文件系統,本地代碼或數據庫連接上的資源的情況?

回答

15

簡短的回答是,servlet容器通過使用單獨的類加載器爲每個應用程序隔離的應用程序 - 通過單獨的類加載器加載的類(即使當從同一物理類文件)是彼此不同的。然而,類加載器共享一個共同的父類加載器,並且容器可能提供許多其他容器範圍的資源,因此這些應用程序並不完全相互隔離。例如,如果兩個應用程序共享一些通用代碼,每個應用程序在其戰爭中都包含相同的jar,那麼每個應用程序都會從​​jar中加載它們自己的實例以及一個類的靜態變量(例如單例)在一個應用程序中將不同於另一個應用程序中同一類的靜態變量。

現在,例如,應用程序嘗試使用java.util.Logger(並且可能不包括他們自己的Logger類的實例在他們的war文件中)。每個應用程序自己的類加載器都不會在war文件中找到該類,因此它們將推遲到它們的父類加載器,這可能是共享的,容器範圍的類加載器。父類加載器將加載Logger類,然後這兩個應用程序將共享相同的Logger類。

5

同一容器中的Servlet將共享一些資源。我認爲應該可以在同一個容器中部署相同的Web應用程序兩次,只要您給每個不同的名稱並且它們不會在特定資源上發生衝突。這在理論上與部署兩個不同的小服務程序相同,而這些服務小程序恰好具有相同的實現,我們一直都在這樣做。

一些共享資源,把我的頭頂部(我不是專家,所以沒有引用任何的這個!):

  • 庫(罐)中的tomcat/common/lib目錄( Tomcat 5)或tomcat/lib(Tomcat 6)。
  • 設置在全局server.xml中,web.xml中,Tomcat的users.xml中
  • OS提供的東西,比如標準輸入/輸出/標準錯誤,網絡套接字,裝置,文件等
  • 日誌系統。
  • Java系統屬性(System.getProperty(),System.setProperty())
  • 我懷疑...靜態變量?我不確定ClassLoader設計是否會阻止這種情況發生。
  • 記憶。這是最常見的問題:一個servlet可以通過消耗所有內存來拒絕其他可用性。
  • CPU - 尤其是多線程應用程序。在HotSpot JVM上,每個Java線程實際上都是一個OS級別的線程,這些線程很昂貴,而且您不需要超過幾千個線程。

無疑有更多的。

如果您使用的是安全管理器,則其中很多都受到安全管理員的保護。

+3

靜態變量是每個類加載器 – 2010-12-22 21:09:46

+0

對於共享資源列表+1,關於來自Pangea的靜態變量的說明與我特別相關 – chrisbunney 2010-12-22 22:15:41

2

我相信隔離是在類加載器中。即使兩個應用程序使用相同的類名稱和包,它們的類加載器也會加載與應用程序一起部署的類。

相關問題