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

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

在这里,我们创建了 .war (或其他任何地方),将其配置为生产(可能为多个盒子创建大量工件)并将生成的工件放置在生产服务器上。

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

构建工件 生产盒

在这里,使用日常在开发人员盒子上本地构建和部署的相同流程来部署到生产环境。

  • 优点: :维护一个流程;并且通过频繁使用进行了大量测试/验证。在工件创建时定制配置可能比定制预构建工件更容易;不需要二进制工件的版本控制。
  • 缺点: :所有生产盒都可能需要复杂的开发工具;部署人员需要了解构建过程;你 不是 部署您测试的内容

我主要使用第二个过程,诚然是出于必要(没有时间/优先级进行另一个部署过程)。就我个人而言,我不相信“生产盒必须清除所有编译器等”之类的论点,但我 查看部署您测试过的内容的逻辑(而不是构建另一个工件)。

然而,Java 企业应用程序对配置非常敏感,使用两个进程来配置工件感觉就像自找麻烦。

想法?

更新

这是一个具体的例子:

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

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

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

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

所以,问题是:

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

解决方案

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

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

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

  1. 测试更改并检查 Subversion。(不一定按这个顺序;我们不要求测试提交的代码。我是唯一的全职开发人员,因此 SVN 树本质上是我的开发分支。你的旅费可能会改变。)

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

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

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

其他提示

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

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

存在配置服务,例如重量级 动物园管理员, ,并且大多数容器允许您使用 JNDI 进行一些配置。这些会将配置与构建分开,但可能有点过分了。然而,它们确实存在。很大程度上取决于您的需求。

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

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

这就是我目前正在努力设置、使用的 AnthillPro.

编辑:我们现在正在使用 哈德逊. 。强烈推荐!

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

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

更新具体示例

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

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

  2. 可能会重新考虑是否需要将配置文件放入 .war 文件中。将其放在类路径中或在服务器启动时在执行命令行中指定属性是否足够。

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

使用 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 文件,然后部署到目标环境。一个过程,实际上只需单击 Anthill 中的一个按钮即可。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top