9

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

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

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

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

生产箱上构建工件

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

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

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

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

想法?

更新

这是一个具体的例子:

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

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

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

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

所以,问题是:

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

7 回答 7

7

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

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

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

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

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

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

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

于 2008-09-26T21:10:59.347 回答
3

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

于 2008-09-26T20:32:44.337 回答
1

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

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

于 2008-09-26T20:32:37.257 回答
1

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

于 2008-09-26T20:39:55.100 回答
1

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

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

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

于 2008-09-26T22:03:26.960 回答
0

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

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

具体示例的更新

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

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

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

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

于 2008-09-26T21:08:40.163 回答
0

使用 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中单击一个按钮。

于 2008-10-06T22:06:06.107 回答