11

我有一个 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次,占用大量磁盘空间
  • 使用符号链接创建 webapp/{app1,app2,appN} 文件夹,指向 app.war 的扩展版本。这可以防止磁盘空间爆炸,但是 JVM 仍然将许多重复的 JAR 加载到内存中
  • 使用一些共享 lib 文件夹来包含大多数 jars(以及前两个选项的组合)。

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

有任何想法吗?

4

5 回答 5

5

Jetty 通过所谓的叠加层增加了对您正在寻找的内容的支持。

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

从wiki页面复制一点:

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

抱歉有点跑题了,但在我看来,您的场景大喊“多租户”应用程序,因此您有一个应用程序可以为多个“租户”(客户)提供服务。

对于多租户设置,必须考虑以下注意事项:

多租户的好处:

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

缺点:

  • 代码将变得更加复杂,因为查询需要确保客户之间的“区别”有效,而不会意外地将客户暴露给彼此的数据。
于 2012-04-17T09:07:22.440 回答
1

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

于 2012-04-17T01:07:37.390 回答
0

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

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

如果您真的想要一个动态增长的解决方案,那么您应该寻求消除单点故障,而不是尝试将您的整个世界集中在一起。

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

于 2012-04-17T01:34:16.960 回答
0

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

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

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

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

于 2012-04-17T01:58:42.883 回答