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

chr*_*ney 12 java tomcat web-applications java-ee

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

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

如下所示: 替代文字

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

然而,一位同事根据他们尝试这种做法的经验不同意.

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

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

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

如果是的话,他们如何做到的?

如果不是,为什么会发生干扰?

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

Ber*_*t F 16

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

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

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


mik*_*vdg 6

同一容器中的Servlet将共享一些资源.我认为应该可以在同一个容器中两次部署相同的Web应用程序,前提是您为每个Web应用程序指定一个不同的名称,并且它们不会在特定资源上发生冲突.理论上这与部署两个不同的servlet相同,这些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可以通过占用所有内存来拒绝其他可用性.
  • CPU - 尤其是多线程应用程序.在HotSpot JVM上,每个Java线程实际上都是一个操作系统级别的线程,这些线程很昂贵,而且你不需要超过几千个.

毫无疑问还有更多.

如果您使用安全管理器,许多安全管理器都会对其进行保护.

  • 静态变量是每个类加载器 (3认同)