servlet容器是否会阻止Web应用程序互相干扰?它们是如何做到的?

时间:2010-12-22 20:34:22

标签: java web-applications tomcat java-ee

我知道一个servlet容器,比如Apache Tomcat,在JVM的单个实例中运行,这意味着它的所有servlet都将在同一个进程中运行。

我也知道servlet容器的体系结构意味着每个Web应用程序都存在于自己的上下文中,这表明它与其他Web应用程序是隔离的。

如下所示: alt text

接受每个Web应用程序是隔离的,我希望您可以创建相同Web应用程序的2个副本,更改每个Web应用程序的名称和上下文路径(以及任何其他相关配置),并且并行运行它们一个影响另一个。 this question的答案似乎支持这种观点。

但是,一位同事根据他们尝试这种做法的经验不同意。

他们拿了一个Web应用程序并尝试在同一个servlet容器中运行2个单独的实例(具有不同的名称等),并且遇到了2个实例冲突的问题(我无法详细说明,因为我没有参与其中工作)。

基于此,他们认为,由于Web应用程序在相同的进程空间中运行,因此它们不能被隔离,诸如类属性之类的东西最终会被无意中共享。 This answer似乎暗示同样的事情

这两个观点似乎不兼容,所以我问你: servlet容器是否阻止部署到同一容器的Web应用程序相互冲突?

如果他们是如何做到的?

如果为什么会发生干扰?

最后,在什么情况下可以分离Web应用程序冲突并导致彼此干扰?,可能涉及文件系统,本机代码或数据库连接上的资源的场景?

3 个答案:

答案 0 :(得分:16)

简短的回答是servlet容器通过为每个应用程序使用单独的类加载器来隔离应用程序 - 由不同的类加载器加载的类(即使来自相同的物理类文件)彼此不同。但是,类加载器共享一个公共父类加载器,容器可能提供许多其他容器范围的资源,因此应用程序不会彼此完全隔离。

例如,如果两个应用程序共享一些公共代码,每个应用程序在其战争中包含相同的jar,那么每个应用程序将从jar中加载它们自己的类实例,并在类中加载一个类的静态变量(例如,单例)一个应用程序将与另一个应用程序中同一个类的静态变量不同。

现在,举例来说,应用程序尝试使用java.util.Logger(并且可能不会在其war文件中包含自己的Logger类实例)。每个应用程序自己的类加载器都不会在war文件中找到该类,因此它们将遵循其父类加载器,这可能是共享的容器范围的类加载器。父类加载器将加载Logger类,然后两个应用程序将共享同一个Logger类。

答案 1 :(得分:6)

同一容器中的Servlet将共享一些资源。我认为应该可以在同一个容器中两次部署相同的Web应用程序,前提是您为每个Web应用程序指定一个不同的名称并且它们不会在特定资源上发生冲突。理论上这与部署两个不同的servlet相同,这些servlet碰巧具有相同的实现,我们一直在这样做。

一些共享资源,在我的头脑中(我不是专家所以不要引用任何一个!):

  • tomcat / common / lib(Tomcat 5)或tomcat / lib(Tomcat 6)中的库(jars)。
  • 全局server.xml中的设置,web.xml,tomcat-users.xml
  • OS提供的东西,例如stdin / stdout / stderr,网络套接字,设备,文件等。
  • 伐木系统。
  • Java系统属性(System.getProperty(),System.setProperty())
  • 我怀疑......静态变量?我不确定ClassLoader设计是否会阻止这种情况。
  • 存储器。这是最常见的问题:一个servlet可以通过占用所有内存来拒绝其他可用性。
  • CPU - 特别是多线程应用程序。在HotSpot JVM上,每个Java线程实际上都是一个操作系统级别的线程,这个线程很昂贵,而且你不需要超过几千个。

毫无疑问还有更多。

如果您正在使用安全管理器,其中许多都受到安全管理员的保护。

答案 2 :(得分:2)

我相信隔离在类加载器中。即使两个应用程序使用相同的类名和包,它们的类加载器也会加载与应用程序一起部署的应用程序。