3

我有大量用 Java 编写并编译为 WAR 文件的不同独立(无状态)Web 服务。我想将它们部署到单个 Web 应用程序服务器。

如果每个 WAR 文件中的服务处理的 URI 都以我可以用作 Web 应用程序名称的前缀开头,那么这将很容易。例如,我可以有

销售战争文件:包含以下代码:
GET http://example.com/sales/widgets
POST http://example.com/sales/widgets
GET http://example.com/sales/sky-hooks

营销战争文件:包含以下代码:
GET http://example.com/marketing/widgets
PUT http://example.com/marketing/sky-hooks

...在这种情况下,我将简单地部署两个名为“sales”和“marketing”的 WAR 文件。然而,我没有那么幸运。相反,组件处理的 URI 路径重叠。像这样的东西:

SALES WAR 文件:包含以下代码:
GET http://example.com/widgets/sales
POST http://example.com/widgets/sales
GET http://example.com/sky-hooks/sales

营销战争文件:包含以下代码:
GET http://example.com/widgets/marketing
PUT http://example.com/sky-hooks/marketing

我的问题是如何(如果有的话)将它们部署在单个 Web 应用程序服务器上。

我愿意接受需要大量工作的建议。例如,我目前最好的想法是构建在常规 URI 路径之前期望组件名称前缀的服务,然后将所有传入流量通过不同的服务器管道传输,该服务器知道每个 URI 模式属于哪个组件并将 URI 修改为添加该前缀。这种方法的困难在于,像 Swagger 这样读取我的源代码的工具会错误地理解 URI 的样子。

有任何想法吗?

4

5 回答 5

6

如果你愿意将 apache 放在你的 web 容器前面,你可以使用apache 的 mod_proxy 将请求转发到正确的位置。

一种可行的方法是,在第一种情况下(销售和营销)将单独的战争部署在单独的前缀上​​,然后使用 ProxyPass 将请求发送到正确的位置:

ProxyPass /widget/sales http://example.com/sales/widget
ProxyPass /sky-hooks/sales http://example.com/sales/sky-hooks

ProxyPass /widget/marketing http://example.com/marketing/widget
ProxyPass /sky-hooks/marketing http://example.com/marketing/sky-hooks

不过,重构您的路由可能是一个更好的主意——它可能很难维护。

(编辑:我最初建议使用 mod_rewrite,但我想让我的答案更具体,看起来这可以纯粹通过代理来完成)

于 2014-06-13T18:48:41.350 回答
4

如果我正确理解您的问题,其中一种解决方案是(我假设使用了 Tomcat,但这应该适用于大多数现代 servlet 容器):

1) 使用不同的前缀部署您的销售和营销战。即,使用您的示例,他们应该能够提供以下网址:

GET http://example.com/sales/widgets/sales
POST http://example.com/sales/widgets/sales 
GET http://example.com/sales/sky-hooks/sales

GET http://example.com/marketing/widgets/marketing
PUT http://example.com/marketing/sky-hooks/marketing

2) 使用UrlRewriteFilter制作轻量级 Web 应用程序,该应用程序将部署到您的 servlet 容器根前缀(对于 Tomcat 称为ROOT.war),并将重写传入请求中的 url 以指向相关的 Web 应用程序。

换句话说,传入的请求如下:

/widgets/sales

将转换为:

/sales/widgets/sales

...并交付给saleswebapp。

同样,在响应网址中,例如:

/sales/widgets/sales

将被改写为:

/widgets/sales

3) 将此战争部署到您的 servlet 容器的根目录。

这种方法有点类似于@nont 建议的方法,但不需要 apache 作为前端,因为重写功能将由根 Web 应用程序处理(UrlRewriteFilter 基本上实现了 mod_rewrite 功能)。

换句话说,您将能够将所有应用程序(包括部署到根前缀的重写应用程序)部署到单个服务器,从而减轻对额外中间代理/重写服务器的需求。

于 2014-06-18T11:44:51.663 回答
1

首先,确定如何配置部署

您确定绝对 URI 必须重叠吗?上下文根将作为每个服务支持的路径的前缀,除非绝对路径以某种方式被编码到应用程序本身中。第一步是通过唯一的上下文根或应用程序实例启用对每个 WAR 文件的直接访问。

选项 1:显式设置每个 WAR 文件的上下文根

war 文件的上下文根是在部署时设置的。对于某些服务器,可以使用外部部署描述符在 Web 应用程序之外进行设置。对于 Tomcat,它可能嵌入在 META-INF/context.xml 中。有关详细信息,请参阅http://tomcat.apache.org/tomcat-7.0-doc/config/context.html

选项 2:使用多个容器分离上下文根实例

或者,将每个 war 文件部署到 Java EE servlet 容器的单独实例,每个实例运行在不同的端口上。这将解决硬编码绝对路径情况下的部署冲突。

最后,设置一个虚拟主机并通过 Apache 和 mod_jk 代理请求

一旦上下文根实例可以通过上述方法之一进行唯一访问,就可以配置一个 Apache 实例作为反向代理。首先,设置一个虚拟主机来处理对外部可见 URI 的请求。接下来,配置 mod_jk 以将请求路由到正确的 WAR 文件部署。有关详细信息,请参阅http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html 。

事后诸葛亮

上述解决方法对于此类问题是通用的,并且需要一些 Apache 和 Tomcat 配置知识,它们被选为示例反向代理和 Java EE servlet 技术的实现。有关部署约束的更多详细信息将有助于确定最佳解决方案。一般来说,确定哪些内容可以更改和哪些内容不能更改的硬性限制应该可以引导您快速找到解决方案。

于 2014-06-18T01:50:22.560 回答
0

This is a use case for Reverse Proxy. If your web server is Apache, as suggested by @nont proxy_mod can be used to create a reverse proxy.

I know that IBM Http Server (IHS) also allows this mod.

于 2014-06-19T17:07:45.887 回答
0

显而易见的槽点是重命名战争,或重构,以便适当的映射在正确的位置。

其他任何事情都会有点hacky,你不能改变战争名称,甚至像下面这样:

SALES WAR FILE: contains code for the following:
GET http://example.com/webapp1/widgets/sales
POST http://example.com/webapp1/widgets/sales
GET http://example.com/webapp1/sky-hooks/sales

MARKETING WAR FILE: contains code for the following:
GET http://example.com/webapp2/widgets/marketing
PUT http://example.com/webapp2/sky-hooks/marketing

您还可以为路由/过滤创建另一场战争,以适当地重定向所有内容 - 但这也依赖于稍微改变 url。

于 2014-06-11T13:11:24.683 回答