6

我们正在维护一个中等规模的代码库,整合到一个单一的多(多)模块 Maven 项目中。总体而言,整个构建有多达十个不同系统组件(Web 应用程序 (.war)、实用程序 (.jar) 等)的输出工件。

到目前为止,我们的部署过程基于简单的 bash 脚本,这些脚本通过 maven 构建请求的工件,使用有关工件、目标环境和当前构建时间戳的信息标记 scm 存储库,然后将工件上传到所选环境应用程序服务器并发布命令来重新启动正在运行的守护进程。构建工件的配置是通过 Maven 配置文件和资源过滤进行的。所以我们的构建是特定于目标环境的。

这个过程对我们很有帮助,但出于不同的原因,我想朝着更复杂的方法前进。特别是我想摆脱 bash 脚本。

那么关于基于 Maven 的 Java 应用程序的配置、版本控制和部署的最佳实践是什么?

我们的构建是否应该与环境无关,并通过目标系统上的配置文件完成配置?如果是这样,开发人员将如何处理在各种应用程序服务器上部署的配置文件中包含新的配置选项?

我们是否应该使用 Maven-versioning 又名 Maven 发布插件来标记各种构建?

配置像 Jenkins 或 Teamcity 这样的 CI 服务器来为我们构建和可选地部署我们的工件是一个好主意吗?

4

2 回答 2

7

我喜欢认为有两个问题空间:

  • 构建工件(理想情况下与环境无关,因为这意味着 QA 可以获取工件的哈希值,在该工件上运行他们的测试,当需要部署时,验证灰烬并且您知道它已经过 QA。如果您的构建产生不同的工件取决于 QA 的 env 还是 staging env 或生产 env,那么您必须做更多的工作以确保投入生产的工件已经过 QA 测试并已在 staging 中上演)

  • 将工件运送到环境中。在该环境需要配置工件的情况下,运输过程应该包括该配置,或者通过将适当的配置文件放在目标环境中并让工件拾取它,或者通过打开工件、配置它们并将它们密封回去向上(但以可重复和确定的方式)

Maven 是为第一个问题空间而设计的。“Maven 方式”是关于生成与环境无关的构建工件并将它们发布到二进制工件存储。如果您查看 Maven 生命周期,您将看到在工件被deploy编辑到 Maven 存储库(二进制工件存储)之后阶段停止。简而言之,Maven 认为它的工作已经完成。test此外,对于uniting 和ing有生命周期阶段,integration-test这两个阶段都应该可以通过与环境无关的工件来实现,但这并不是您需要的完整测试集......而是要完成您的测试,您需要实际部署将构建的工件放入真实环境中。

许多人试图劫持 Maven 以超越其目标(包括我自己)。例如,您有cargo-maven-pluginship-maven-pluginwhich 涉及 maven 最终游戏之外的方面(即在工件到达 maven 存储库之后)。其中,我个人觉得,ship-maven-plugin(我写的,因此我以前的“包括我自己”)最接近使用“在 maven 之后”,因为默认情况下它被设计为运行,而不是在-SNAPSHOT您检查过的项目版本上运行在磁盘上,而是在它从远程存储库中提取的同一项目的发布版本上,例如

mvn ship:ship -DshipVersion=2.5.1

IMO,货物的目的是在integration-test生命周期的各个阶段使用,但同样,您可以将其劫持用于其他目的。

如果您正在生产收缩包装的软件,即用户购买并安装在其系统上的那种软件,安装程序本身旨在为最终用户环境配置应用程序。让 Maven 构建生成安装程序很好,因为实际的安装程序(至少在某种程度上)与环境无关。好的,它可能是仅 Microsoft Windows 的安装程序,或仅 Linux 的安装程序,但它并不关心它安装在哪台用户机器上。

不过,现在我们倾向于更多地关注软件即服务,因此我们将软件部署到我们控制的服务器上。更容易被拖到“Maven 黑暗面”,其中构建配置文件用于调整构建工件的内部配置(毕竟我们只有三个部署到的环境)并且我们正在快速移动,所以不想花时间让应用程序从外部到构建的工件(听起来很熟悉?)中获取特定于环境的配置。我称之为黑暗面的原因是你真的在与 maven 想要的工作方式作斗争......你总是想知道本地存储库中的 jar 是否是使用不同的配置文件构建的,所以你最终不得不做完整的始终保持干净的构建。pom.xml...试想一下,如果您遵循 maven 方式,您只需从存储库中获取工件并将其移动到不同的环境中,未经修改,不受干扰,并使用 MD5、SHA1(希望是 GPG)签名来证明它是同一个神器。

所以,你问,我们如何编码运输到生产......

那么有很多方法可以解决这个问题。他们都有一套相似的核心原则,即

  • 将发送到环境的配方保存在源代码控制系统中

  • 理想情况下,配方应该有两个部分,一个与环境无关的部分和特定于环境的部分。

您可以使用良好的旧 bash 脚本,或者您可以使用更“现代”的工具,例如为第二个问题空间设计的 chef 和 puppet。

建议

您应该为正确的工作使用正确的工具。

如果是我,我会这样做:

  • 使用 Maven 发布插件削减发布

  • 构建的工件应该始终与环境无关。

  • 构建的工件应包含所有配置选项的“合理默认值”。换句话说,如果缺少没有合理默认值的必需配置选项,它们应该快速爆炸,或者如果未指定可选选项,它们应该以合理的方式执行。所需配置选项的一个示例可能是数据库连接详细信息(除非应用程序乐于使用内存数据库运行)

  • 在厨师 vs 傀儡战争中选择一方(无论哪一方,如果你愿意,你可以改变立场。如果你有 ANT 思维,厨师可能更适合你,如果你喜欢依赖管理魔法,傀儡可能更适合你更好的)

  • 开发人员应该在定义用于部署的主厨/木偶脚本方面有发言权,至少是这些脚本的与环境无关的部分。

  • 操作应定义 Chef/puppet 部署的生产环境特定细节

  • 将所有这些脚本保存在 SCM 中。

  • 使用 Jenkins 或任何 CI 来自动化尽可能多的步骤。Jenkins 的升级构建插件是您的朋友。

  • 您的最终游戏是每次提交,只要它通过了所有必需的测试,*可以*自动部署到生产中(或者也许有人说“继续”)......注意不要说你实际上是这样做的对于每一次提交,只有你可以

于 2013-02-02T11:03:07.340 回答
0

What I have used in the past which work well is to use Apache Karaf+iPOJO with my version control which was subversion (I would use git today)

What the version control allowed be to do was deploy a versioned copy of Apache Karaf and my configuration files. Any changes made from development or on the production system (when something needed an urgent fix) would still be traced and could be checked in (including information about who made what change when)

What Apache Karaf supports is dynamic deployment of maven libraries from your maven repository. i.e. you have configuration files which specify the versions of jar you want tot release and it will download them as required from your maven repo and run them. The iPOJO adds components for these models which you can configure using properties values (again versioned)

This assumes you have control of the end-to-end development to deployment, but can work very well even with multiple remote sites.

于 2013-02-01T16:29:41.207 回答