我有大量不同的独立(无状态)Web服务,用Java编写并编译为WAR文件。我想将它们部署到单个Web应用程序服务器。
如果每个WAR文件中的服务处理的URI都以我可以用作Web应用程序名称的前缀开头,那么这很容易。例如,我可以
SALES WAR FILE:包含以下代码:
获得http://example.com/sales/widgets
邮寄http://example.com/sales/widgets
获取http://example.com/sales/sky-hooks
营销战争文件包含以下代码:
获得http://example.com/marketing/widgets
PUT http://example.com/marketing/sky-hooks
...在这种情况下,我只需在名称“sales”和“marketing”下部署两个WAR文件。但是,我不是那么幸运。相反,组件处理的URI路径重叠。像这样:
SALES WAR FILE:包含以下代码:
获得http://example.com/widgets/sales
邮寄http://example.com/widgets/sales
获取http://example.com/sky-hooks/sales
营销战争文件包含以下代码:
获得http://example.com/widgets/marketing
PUT http://example.com/sky-hooks/marketing
我的问题是如何(如果有的话)我可以在单个Web应用程序服务器上部署它们。
我愿意接受需要大量工作的建议。例如,我最好的想法是在常规URI路径之前构建期望组件名称前缀的服务,然后通过不同的服务器管理所有传入流量,该服务器知道每个URI模式属于哪个组件并将URI修改为添加该前缀。这种方法的难点在于,像Swagger这样的工具读取我的源代码会误解URI的样子。
有什么想法吗?
答案 0 :(得分:6)
如果您愿意将apache放在网络容器前,可以使用apache's mod_proxy to forward request to the right place.
这可行的一种方法是,在第一种情况下(销售和市场营销)将单独的战争部署在不同的前缀上,然后使用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,但我想让我的答案更具体,看起来这可以完全用代理完成)
答案 1 :(得分: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
...并发送到sales
webapp。
同样,回复网址如:
/sales/widgets/sales
将被重写为:
/widgets/sales
3)将此war部署到servlet容器的根目录。
这种方法有点类似于@nont建议的方法,但不需要apache作为前端,因为重写功能将由root web应用程序处理(UrlRewriteFilter基本上实现了mod_rewrite功能)。
换句话说,您将能够将所有应用程序(包括部署到根前缀的重写应用程序)部署到单个服务器,从而减少对额外中间代理/重写服务器的需求。
答案 2 :(得分: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技术。有关部署约束的其他详细信息将有助于确定最佳解决方案。一般而言,确定可能更改的内容与可能未更改内容的硬约束应该可以指导您快速找到解决方案。
答案 3 :(得分: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。
答案 4 :(得分:0)
这是反向代理的用例。如果您的Web服务器是Apache,则可以使用@nont proxy_mod建议创建反向代理。
我知道IBM Http Server(IHS)也允许这个mod。