有效地部署相同WAR的多个实例(不同的上下文,相同的容器)

时间:2012-04-16 23:52:04

标签: java tomcat glassfish jetty war

我有一个WAR(app.war)和一个容器(Tomcat,Jetty,Glassfish等等)。 我的目标是按需部署容器上数百个同一Web应用程序的实例。

http://foo/app1 --> app.war
http://foo/app2 --> app.war
http://foo/app3 --> app.war 
...
http://foo/appN --> app.war

实现这一目标的一些明显方法:

  • 在Tomcat中,为每个应用程序(名为appN.xml)创建一个context.xml文件,所有这些文件都指向同一个WAR。其他容器也有类似的方法
    • 这种方法有问题:它会爆炸WAR N次,占用大量磁盘空间
  • 使用符号链接创建指向app.war爆炸版的webapp / {app1,app2,appN}文件夹。这可以防止磁盘空间爆炸,但JVM仍然会将许多重复的JAR加载到内存
  • 使用一些共享的lib文件夹来包含大多数jar(以及前两个选项的组合)。

我想知道是否有更好的方法来做到这一点。理想情况下,创建新实例不应占用任何更多磁盘空间(边缘配置文件除外),只占用与线程执行堆栈和其他运行时分配相关的内存。

有什么想法吗?

5 个答案:

答案 0 :(得分:5)

Jetty通过所谓的叠加添加了对您所寻找内容的支持。

http://wiki.eclipse.org/Jetty/Tutorial/Configuring_the_Jetty_Overlay_Deployer

从维基页面复制一下:

  • 您可以将WAR文件保持不变,甚至签名,以便明确您已部署的版本。
  • 您为自定义/配置Web应用程序所做的所有修改都是单独的WAR,因此可以轻松识别以便查看和迁移到新版本。
  • 您可以创建参数化模板覆盖,其中包含适用于Web应用程序的许多实例的常见自定义和配置(例如,用于多租户部署)。
  • 由于分层部署清楚地标识了公共和特定于实例的组件,因此Jetty能够共享模板的类加载器和静态资源缓存,从而大大减少了多个实例的内存占用。

答案 1 :(得分:2)

抱歉有点偏离主题,但在我看来,你的情节大喊“多租户”应用程序,这样你就有了一个应用程序可以为多个“租户”(客户)提供服务。

关于多租户设置,必须考虑以下因素:

多租户的好处:

  • 共享代码意味着为一个客户修复的错误是固定的(如果不同的客户对构成错误的内容和构成功能的内容有不同的看法,这也可能是一个缺点。)
  • 群集部署可以共享客户之间的负载(但是,需要确保所有客户都可以使用峰值容量)。

缺点:

  • 代码会变得有点复杂,因为查询需要确保客户之间的“歧视”工作,而不会在意外地将客户暴露给彼此的数据。

答案 2 :(得分:1)

您可以在前端配置Apache(mod_proxy / mod_proxy_ajp),将指定的虚拟主机指向部署在Tomcat上的单个WAR。您的应用程序应按照服务所有请求的方式设计/编写 - 每个网站名称特定配置可以存储在数据库中或作为应用程序中的配置文件 - 您的应用程序只需要探测用户的请求域名到确保应用正确的设置(每个会话一次)。一般来说,您应该能够通过一个应用程序解决这个问题。伟大的开发商是LAZY。

答案 3 :(得分:0)

如果这是用于实验,那么您列出的任何方法都可以使用。

如果这是用于生产,那么我建议不要这样做。虽然我没有测试过所有容器,但我使用过的容器让我相信,只需使用容器配置无头虚拟机就可以了。 Linux VM可以非常小,使用VM技术,您可以根据需要添加或减少任意数量的实例。

如果你真的想拥有一个动态增长的解决方案,那么你应该寻求消除单点故障,而不是试图把你的整个世界变成一个。

如果您确实需要“最多第二次”负载扩展/收缩,那么您应该查看AWS或CloundFoundry。

答案 4 :(得分:0)

如果您使用的是Jetty,则可以通过编程方式添加上下文。

WebAppContext webapp = new WebAppContext();
webapp.setBaseResource(myBaseDirectory);
webapp.setContextPath(myContextPath);

只需在循环中为所有上下文执行此操作。它的磁盘空间开销应该接近于零。

在Tomcat中可能有类似的方法。