【问题标题】:Java Web Deployment: build code, or deploy .war?Java Web 部署:构建代码,还是部署 .war?
【发布时间】:2010-09-13 14:10:42
【问题描述】:

部署 J2EE/Java Web 应用程序的两种主要方式(在非常简单的意义上):

将组装的工件部署到生产盒

在这里,我们在别处创建.war(或其他),将其配置为用于生产(可能为许多盒子创建大量工件)并将生成的工件放在生产服务器上。

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

生产箱上构建工件

在这里,日常用于在开发人员机器上本地构建和部署的相同过程用于部署到生产。

  • 优点:需要维护一个流程;并通过频繁使用进行了大量测试/验证。在创建工件时自定义配置可能比自定义预建工件后记更容易;无需对二进制工件进行版本控制。
  • 缺点:所有生产机器都需要潜在的复杂开发工具;部署人员需要了解构建过程;你没有部署你测试的东西

我主要使用第二个过程,诚然是出于必要(没有时间/优先级进行另一个部署过程)。就我个人而言,我不赞成“生产箱必须清除所有编译器等”之类的论点,但我可以看到部署您测试过的东西的逻辑(而不是构建另一个神器)。

然而,Java Enterprise 应用程序对配置非常敏感,感觉有两个用于配置工件的进程是自找麻烦。

想法?

更新

这是一个具体的例子:

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

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

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

这会创建两个进程来完成同一件事。

所以,问题是:

  • 如果不“在生产环境中编译”,这是否可以避免?
  • 如果没有,这值得吗? “不编译生产”的价值是否大于“不要重复自己”?

【问题讨论】:

    标签: java deployment jakarta-ee


    【解决方案1】:

    存在配置服务,比如重量级的ZooKeeper,大多数容器都可以让你使用JNDI来做一些配置。这些会将配置与构建分开,但可能会过大。但是,它们确实存在。很大程度上取决于您的需求。

    我还使用了一个过程,在该过程中,工件是使用配置值的占位符构建的。当 WAR 被部署时,它被分解并且占位符被替换为适当的值。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        我强烈推荐“将组装的工件部署到生产箱”,例如 war 文件。这就是为什么我们的开发人员使用相同的构建脚本(在我们的例子中是 Ant)来在他们的开发沙箱上构建战争,就像用于创建 finally 工件一样。这样就可以调试代码本身,更不用说完全可重复了。

        【讨论】:

        • 我不明白;如果开发人员使用相同的脚本,那怎么不是“在生产盒上生产工件”场景?你有一个脚本来编译和创建战争,一个脚本来部署它吗?
        【解决方案4】:

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

        如果您问的是与可重复流程创建相关的问题,那么答案需要基于您愿意忍受的疼痛的位置和数量。使用 .war 文件可能会带来更多的前期痛苦,以节省测试和部署周期的工作量。使用源文件和构建工具可能会节省前期成本,但您将不得不忍受在部署过程后期处理问题的额外痛苦。

        具体示例更新

        与您的示例相关的两件事要考虑。

        1. .war 文件只是具有备用扩展名的 .zip 文件。您可以使用标准 zip 实用程序替换配置文件。

        2. 可能重新考虑将配置文件放入 .war 文件中的需要。将它放在类路径上或在服务器启动时在执行命令行中指定属性就足够了吗?

        一般来说,我会尝试保持特定于部署位置的部署配置要求。

        【讨论】:

          【解决方案5】:

          我坚决反对在生产环境中进行构建,因为这意味着您使用的构建版本与您测试时使用的版本不同。这也意味着每台部署机器都有不同的 JAR/WAR 文件。如果不出意外,请进行统一构建,以便在错误跟踪时不必担心服务器之间的不一致。

          此外,如果您可以轻松地在构建和创建它的源之间进行映射,则无需将构建放入版本控制中。

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

          1. 测试更改并签入 Subversion。 (不一定按这个顺序;我们不需要测试提交的代码。我是唯一的全职开发人员,所以 SVN 树本质上是我的开发分支。你的里程可能会有所不同。)

            李>
          2. 将 JAR/WAR 文件复制到以 Subversion 修订号命名的共享目录中的生产服务器。 Web 服务器只有读取权限。

          3. 部署目录包含到以修订命名的目录中的文件的相对符号链接。这样,目录列表将始终向您显示生成运行版本的源代码版本。部署时,我们会更新一个日志文件,它只不过是一个目录列表。这使得回滚变得容易。 (不过有个问题;Tomcat 根据实际文件的修改日期检查新的 WAR 文件,而不是符号链接,因此我们在回滚时必须触及旧文件。)

          我们的网络服务器将 WAR 文件解压到本地目录。该方法是可扩展的,因为 WAR 文件位于单个文件服务器上;我们可以拥有无​​限数量的 Web 服务器,并且只进行一次部署。

          【讨论】:

          • 如果您有信心可以从源头重新创建战争,为什么不在生产盒上构建它呢?如果战争被视为神圣,它似乎应该进入版本控制......
          • 一方面,我不相信我可以完全从源代码创建它。事情没有正确地检查到 SVN 中,或者我需要一个特殊的生产环境测试构建来难以重现错误。另一方面,我们有 WAR 的备份; SVN 历史记录用于调试,而不是回滚。
          • 可以在生产箱上进行自动部署程序,但不要在其上进行构建(因为您随后需要测试构建等)。跨度>
          【解决方案6】:

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

          这是我目前正在使用AnthillPro 设置的。

          编辑:我们现在使用Hudson。强烈推荐!

          【讨论】:

          • 同上这个答案,只是我们使用开源构建服务器 Hudson 代替。构建能够自动构建、测试并生成所有构建产品以进行测试和部署的服务器是一件好事。
          【解决方案7】:

          使用 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 可以做到这一切,我们使用 anthill 来管理 ant。 ant 构建war 文件,替换文件路径,更新war 文件,然后部署到目标环境。一个过程,其实就是蚁丘中的一键点击。

          【讨论】:

            猜你喜欢
            • 2014-05-30
            • 2020-03-22
            • 1970-01-01
            • 1970-01-01
            • 2016-12-28
            • 2014-10-03
            • 2015-09-16
            • 1970-01-01
            • 2018-06-12
            相关资源
            最近更新 更多