Servlet容器是否可以防止Web应用程序互相干扰,以及如何做到这一点?

问题描述 投票:12回答:4

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

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

如此处所示:“替代文字”

接受每个Web应用程序都是隔离的,我希望您可以创建一个相同Web应用程序的2个副本,更改每个Web应用程序的名称和上下文路径(以及任何其他相关配置),并在没有一个Web应用程序的情况下并行运行它们影响对方。 this question的答案似乎支持此视图。

但是,同事基于他们尝试这样做的经验而不同意。

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

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

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

如果他们如何做?

如果为什么会发生干扰?

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

java web-applications tomcat java-ee
4个回答
16
投票

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

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

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


6
投票

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

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

  • tomcat / common / lib(Tomcat 5)或tomcat / lib(Tomcat 6)中的库(jar)。
  • 全局server.xml,web.xml,tomcat-users.xml中的设置
  • 操作系统提供的东西,例如stdin / stdout / stderr,网络套接字,设备,文件等。>
  • 日志系统。
  • Java系统属性(System.getProperty(),System.setProperty())
  • 我怀疑...静态变量?我不确定ClassLoader设计是否会阻止这种情况。
  • 内存。这是最常见的问题:一个servlet通过消耗所有内存来拒绝其他servlet的可用性。
  • CPU-尤其是在多线程应用程序中。在HotSpot JVM上,每个Java线程实际上都是一个OS级别的线程,这很昂贵,并且您不希望使用数千个。
  • 毫无疑问,还有更多。

如果使用的话,其中许多东西都由安全管理器保护。


2
投票

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


0
投票

我在web.xml文件中提到了带有多个servlet的单个WAR,并且在公共类中有一些静态变量。我看到它们正在跨servlet共享。

© www.soinside.com 2019 - 2024. All rights reserved.