Java 高效地部署同一战争的多个实例(不同上下文、相同容器)

Java 高效地部署同一战争的多个实例(不同上下文、相同容器),java,tomcat,glassfish,jetty,war,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中,为每个应用程序创建一个contex

我有一个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中,为每个应用程序创建一个context.xml文件(名为appN.xml),所有这些文件都指向同一个WAR。其他容器也有类似的方法
    • 这种方法的问题是:它会将战争爆发N次,占用大量磁盘空间
  • 使用符号链接创建指向app.war分解版本的webapp/{app1,app2,appN}文件夹。这可以防止磁盘空间爆炸,但JVM仍在向内存加载许多重复的JAR
  • 使用一些共享库文件夹来包含大多数JAR(以及前两个选项的组合)
我想知道是否有更好的方法来做到这一点。理想情况下,创建一个新实例不应该占用更多的磁盘空间(除了边缘配置文件),而应该只占用与线程执行堆栈和其他运行时分配相关的内存


有什么想法吗?

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

如果这是一个实验,那么您列出的任何方法都可以工作

如果这是为了生产,那么我建议不要这样做。虽然我没有测试所有的容器,但我使用的容器让我相信,简单地为无头虚拟机提供容器会更有弹性。Linux虚拟机可以非常小,使用虚拟机技术,您可以根据需要添加或减少任意多的实例

如果你真的想拥有一个动态增长的解决方案,那么你应该设法消除单一的失败点,而不是试图将你的整个世界都整合到一个整体中


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

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

WebAppContext webapp = new WebAppContext();
webapp.setBaseResource(myBaseDirectory);
webapp.setContextPath(myContextPath);
在所有上下文中循环执行此操作。它的磁盘空间开销应该接近于零


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

很抱歉有点离题,但在我看来,您的场景会显示“多租户”应用程序,这样您就有了一个为多个“租户”(客户)服务的应用程序

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

  • 客户无法访问彼此的数据(如果他们将数据存储在同一数据库、同一模式中,并使用“鉴别器”字段分隔数据)。这可以通过使用Spring Security和
  • Hibernate具有4.0版的内置功能
  • 这两个问题也可能有用
    • (用于使用不同的数据源(每个客户的不同数据库或同一数据库上的不同模式)
多租户的好处:

  • 共享代码意味着为一个客户修复的bug是为所有客户修复的(如果不同的客户对什么构成bug以及什么构成特性有不同的看法,这也可能是一个缺点)
  • 集群部署可以在客户之间共享负载(但是,需要确保所有客户都可以使用峰值容量)
缺点:

  • 代码将更加复杂,因为查询需要确保客户之间的“区别”有效,而不会意外地将客户暴露给彼此的数据

Jetty通过所谓的覆盖层,为您之前寻找的内容添加了支持

从wiki页面复制一个位:

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

你会考虑把应用程序改写为多线程的应用程序吗?如果有100多个完全相同的战争和代码的实例,我会考虑设计1个将被部署到root上下文的战争?@ BeY23,一个复杂的解释可以帮助我处理一些我正在做的事情。你有没有机会提供一个?我发布了一个AN。回答如下,但如果你告诉我们为什么要这样做,我可能会发布一个更好的。谢谢你的提示;)这是一种多租户设置。我需要为每个应该在自己的上下文中运行的用户提供一个“相同”的应用程序。应用程序以这种方式构建的原因超出了本文的范围,但有一个强有力的商业案例推动了这一点。如果你给我们商业案例,我可能会有更多的建议。它与安全相关吗?不同的语境也无济于事。是否每个用户都需要自己的URL路径?您可以通过URL重写来实现这一点。或者给每个用户一个子域(这很容易做到)