Java Web部署:构建代码还是部署.war?

时间:2020-03-06 14:48:21  来源:igfitidea点击:

部署J2EE / Java Web应用程序的两种主要方法(非常简单):

将组装好的工件部署到生产箱

在这里,我们在其他地方创建.war(或者其他任何东西),对其进行配置以进行生产(可能会为多个盒子创建大量工件),并将所得的工件放置在生产服务器上。

  • 优点:生产盒上没有开发工具,可以直接重用测试中的工件,部署人员不需要构建过程的知识
  • 缺点:创建和部署工件的两个过程;预构建工件的潜在复杂配置可能使流程难以编写脚本/实现自动化;必须版本二进制工件

在生产盒上构建工件

在这里,每天用于在开发人员盒上本地构建和部署的相同过程用于部署到生产中。

  • 优点:维护一个过程;并且已通过频繁使用进行了严格的测试/验证。在创建工件时可能更容易自定义配置,而不是自定义预先构建的工件后记;无需对二进制工件进行版本控制。
  • 缺点:所有生产盒都需要复杂的开发工具;部署人员需要了解构建过程;我们没有部署测试的产品

我主要使用了第二个过程,当然,这是不必要的(没有时间/优先级用于另一个部署过程)。就我个人而言,我不需要购买"生产环境必须清除所有编译器等"之类的参数,但是我可以看到部署测试对象的逻辑(而不是构建另一个工件)。

但是,Java Enterprise应用程序对配置非常敏感,感觉就像在请求两个用于配置工件的流程那样麻烦。

有什么想法吗?

更新

这是一个具体的例子:

我们使用OSCache,并启用磁盘缓存。配置文件必须位于.war文件中,并且它引用文件路径。在每种环境下,此路径都是不同的。构建过程将检测用户的配置位置,并确保放置在war中的属性文件对于他的环境是正确的。

如果我们要使用构建过程进行部署,则需要为生产环境创建正确的配置(例如" production.build.properties")。

如果要遵循"将组装好的构件部署到生产箱中",我们将需要一个额外的过程来提取(不正确的)OSCache属性并将其替换为适合生产环境的OSCache属性。

这将创建两个过程来完成同一件事。

因此,问题是:

  • 如果不"按生产进行编译",这是可以避免的吗?
  • 如果没有,这值得吗? "不进行生产编译"的价值大于"不重复自己"的价值吗?

解决方案

存在一些配置服务,例如重量级的ZooKeeper,大多数容器使我们能够使用JNDI进行一些配置。这些将配置与构建分开,但可能会过大。但是,它们确实存在。在很大程度上取决于需求。

我还使用了一个过程,其中使用配置值的占位符构建了工件。部署WAR时,它将爆炸并用适当的值替换占位符。

我工作过的大多数地方都使用第一种方法,将特定于环境的配置信息单独部署(在战争/耳朵之外)(并且很少更新)。

我强烈建议"将组装好的工件部署到生产箱中",例如war文件。这就是为什么我们的开发人员使用相同的构建脚本(在我们的案例中为Ant)在其开发沙箱上构建战争的原因,就像用来创建final工件一样。这样,它以及代码本身都被调试了,更不用说完全可重复了。

如果我们要问的是与配置管理有关的问题,那么答案必须基于我们认为是托管工件的内容。从CM的角度来看,让源文件的某些集合在一个环境中而不在另一个环境中工作是不可接受的。 CM对环境变量,优化设置,编译器和运行时版本等敏感,因此我们必须考虑这些因素。

如果我们要问的是有关可重复过程创建的问题,那么答案必须基于我们愿意忍受的痛苦的位置和数量。为了节省测试和部署周期的工作量,使用.war文件可能会涉及更多的前期麻烦。使用源文件和构建工具可以节省前期成本,但是在部署过程的后期处理问题时,我们将不得不承受额外的痛苦。

更新具体示例

相对于示例,需要考虑两件事。

  • .war文件只是具有备用扩展名的.zip文件。我们可以使用标准zip实用程序替换配置文件。
  • 可能会重新考虑是否需要将配置文件放在.war文件中。将其放在类路径上或者在服务器启动时在执行命令行中指定属性就足够了。

通常,我尝试保留特定于部署位置的部署配置要求。

我坚决反对在生产环境中进行构建,因为这意味着我们使用的构建与测试时使用的构建不同。这也意味着每台部署计算机都有一个不同的JAR / WAR文件。如果没有其他问题,只需进行统一构建即可,以便在进行错误跟踪时,我们不必担心服务器之间的不一致。

另外,如果我们可以轻松地在内部版本与创建它的源之间进行映射,则无需将内部版本放入版本控制中。

在我工作的地方,我们的部署过程如下。 (这是在Linux和Tomcat上。)

  • 测试更改并签入Subversion。 (不一定按此顺序;我们不需要测试提交的代码。我是唯一的全职开发人员,因此SVN树本质上是我的开发分支。工作量可能会有所不同。)
  • 将JAR / WAR文件复制到以Subversion修订版本号命名的共享目录中的生产服务器。 Web服务器仅具有读取访问权限。
  • 部署目录包含指向修订版本目录中文件的相对符号链接。这样,目录列表将始终向我们显示源代码的哪个版本产生了运行版本。部署时,我们更新的日志文件只不过是目录列表。这使回滚变得容易。 (不过,有一点很麻烦; Tomcat在实际文件的修改日期而不是符号链接的修改日期之前检查新的WAR文件,因此在回滚时,我们必须触摸旧文件。)

我们的Web服务器将WAR文件解压缩到本地目录中。由于WAR文件位于单个文件服务器上,因此该方法具有可伸缩性。我们可以拥有无​​限数量的Web服务器,并且只能进行一次部署。

更新了具体方案,请参见上文

我会推荐使用支持分布式构建的持续集成解决方案。检入SCM的代码可以触发构建(用于立即测试),我们可以安排构建以创建用于质量检查的工件。然后,我们可以将这些工件升级到生产环境并进行部署。

目前,这是我正在使用AnthillPro进行设置的内容。

编辑:我们现在正在使用哈德森。极力推荐!

使用1个打包的war文件进行部署是一个好习惯。
我们使用ant替换环境之间不同的值。我们使用<变量将文件检入,该变量将被我们的ant脚本替换。 ant脚本替换文件中的正确项目,然后在部署到每个文件之前更新war文件。

<replace file="${BUILDS.ROOT}/DefaultWebApp/WEB-INF/classes/log4j.xml" token="<" value="${LOG4J.WEBSPHERE.LOGS}"/>

<!-- update the war file We don't want the source files in the war file.-->
<war basedir="${BUILDS.ROOT}/DefaultWebApp" destfile="${BUILDS.ROOT}/myThomson.war" excludes="WEB-INF/src/**" update="true"/>

总而言之,我们使用蚁丘来管理蚂蚁。
ant构建war文件,替换文件路径,更新war文件,然后部署到目标环境。一个过程,实际上是在蚁丘中单击按钮。