【问题标题】:Single virtual tomcat application which serves multiple contexts服务于多个上下文的单个虚拟 tomcat 应用程序
【发布时间】:2012-02-15 04:05:21
【问题描述】:

我有多个客户:

  • 客户端 1 - 40 个用户
  • 客户端 2 - 50 个用户
  • 客户端 3 - 60 个用户

我有一个应该为所有客户端提供服务的 Web 应用程序。 应用程序被部署到 Tomcat 中。每个客户都有自己的数据库。

我想要实现的是为所有客户端提供服务的单个 Web 应用程序实例。客户端(以及要连接的数据库)由 URL 中的上下文路径标识。

即我暗示以下场景:

  1. 一些用户请求http://mydomain.com/client1/
  2. Tomcat 调用我的应用程序的单个实例(无论请求哪个上下文)
  3. 我的应用程序处理请求的其余部分,认为它已部署到 /client1 上下文路径,即所有重定向或相对 URL 应针对 http://mydomain.com/client1/ 解析

当客户端 2 请求 http://mydomain.com/client2/ 时,我希望我的应用程序(同一个实例)现在处理它,就像它部署到 /client2 上下文路径一样。

Tomcat 可以做到这一点吗?

【问题讨论】:

  • 三次部署同一个应用程序(配置不同)会更容易也更安全,每次都有自己的配置和上下文路径。按照您的操作方式,来自客户端 1 的人可以轻松访问客户端 2 的数据。您最终会重新实现 Tomcat 为您实现的功能。
  • 嗯,应用程序很大,当然我没有 3 个客户,但还有更多。我只是想减少内存消耗并防止多次加载同一个应用程序。
  • 我可以看到减少内存消耗的愿望,特别是在应用程序非常大的情况下。然而,在我看来,它的设计已经把它拉到了一个角落。最好的方法一直是 1) 要么拥有三个不同配置的部署(如 JB Nizet 所说),要么 2) 拥有三个物理上不同的容器进程,每个容器进程托管一个单独的、不同配置的部署。哪个更好取决于应用程序和 JEE 容器。您正在尝试手动实现应用程序/容器隔离。 "ZOMG! SNAFU" 有很多方法,所以如果你必须走这条路,请谨慎行事。
  • 内存很便宜。软件工程师(和律师)不是:-)

标签: java tomcat configuration web


【解决方案1】:

您的应用程序必须这样做,而不是 tomcat。现在您可以在三个新的上下文(client1、client2、client3)中部署您的应用程序,但数据库的配置略有不同,如果您小心使用相对 URL(即不要执行 /images 之类的操作),那么您可以这样做没有变化。这是使您的应用程序可重用的透明方式,因为您的应用程序不知道您有 3 个不同的自身实例在运行的全局图片。这意味着您可以轻松部署更多或更多,而无需更改您的应用程序。您只需配置一个新实例即可。这只要求您不要对资源使用绝对 URL。使用 ServletContext.getContextPath() 并在 CSS、脚本等中使用 .. 在这里也很有帮助。

以这种方式工作的最大优势之一可能是您的应用不关心全局问题。因为它不参与这些决策,所以您可以在一台 tomcat 服务器上运行 3 个实例,或者如果一个客户端需要更多扩展,它们可以轻松移动到自己的 tomcat 服务器上。通过使您的应用程序可移植,它迫使您处理如何在任何环境中安装您的应用程序。这是水平扩展的支柱,您的情况可以很好地利用它,因为您可以拆分数据库数据而无需重新加入它们(巨大的优势)。您询问的选项不会强迫您处理这个问题,所以到了处理它的时候会很痛苦。

另一个选项涉及更多,需要对您的应用程序进行重大更改才能处理此问题。这是通过解析传入的 URL 并提取客户端的名称,然后使用该名称在配置文件中查找应该用于该客户端的数据库。 SpringMVC 可以处理诸如从 URL 路径中提取变量之类的事情。然后确保将所有内容呈现给他们,使其指向他们的 URL 部分。这可能需要很多与第一个相同的要求。您可以将绝对 URL 用于 javascript、CSS 和图像等内容,但您的应用程序的 URL 必须在运行时重写,以便它与请求客户端相关。好处是您只需加载您的应用程序一次。

顺便说一句,如果您在生产环境中将 CSS、Javascript 和图像托管在 CDN 上,那么这两个选项都必须是相对 URL 感知的。使用 CDN 的优点和缺点也是如此。

虽然这听起来不错,但可能不是一件好事,因为所有客户都使用相同版本的应用。此外,如果您关闭应用程序来修复 client1 进行维护,它会影响所有客户端。如果您认为必须为每个客户端进行自定义,那么此选项将很快变得混乱。升级单个客户端意味着所有客户端都必须升级,并且根据您的业务模型,这可能不兼容。此外,我不完全确定仅运行单个版本的应用程序会节省大量内存,因为大多数应用程序只占用 10MB 加载的代码。绝大多数内存在 VM 中并处理请求,使用单个 Tomcat 实例意味着您共享 VM。在运行 1 或 3 个实例的情况下,您仍然有相同数量的请求。您可能会看到 30 到 100MB 的差异,这在当今世界是小菜一碟,如果您选择仅保存几 MB,则所有其他问题都无法解决。

基本上 Tomcat 中有一些工具可以帮助您执行此操作(多个上下文),但主要取决于您的应用程序来处理此问题,尤其是在它是单个实例的情况下。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-22
    • 2018-09-09
    • 2017-09-18
    • 1970-01-01
    • 2011-09-24
    • 2010-12-20
    • 1970-01-01
    • 2014-05-14
    相关资源
    最近更新 更多