【问题标题】:Generate wars for multiple environments with maven?使用 maven 为多个环境生成战争?
【发布时间】:2020-01-08 18:09:51
【问题描述】:

如何使用 maven 为多个环境生成战争?

  • 我有大约 8 个环境。 dev,dev_local,ci,ci_local,qa,qa_local,prod,prod_local。
  • 我不想为 *_local 环境生成 war 文件。
  • 我有所有环境通用的配置文件。我想避免为各种环境维护这些文件的重复副本。
  • 通用文件可能有一些属性需要针对各种环境进行自定义。
  • 战争中的清单文件应具有特定于环境的信息。
  • 资源文件应该放在WEB-INF/classes 目录下。

【问题讨论】:

  • 没有人通过为每个环境构建单独的二进制文件来配置环境。配置与二进制文件分开保存,以便可以在所有环境中部署相同的二进制文件。
  • 没有人是很多人。
  • @ShaggyInjun 我也会避免为不同阶段构建不同的工件。在大多数情况下,您可以将阶段属性与工件分开。
  • 我不是建立多场战争的拥护者,真的。我遇到了这种情况。我只是需要一种更好的方法来代替它目前正在发生的方式。也许您可以解释将财产与战争分开的好处。在我目前的情况下,两个不同的团队部署到两个不同的生产服务器,分别交付配置文件使团队可以处理的事情变得更加复杂。
  • 好处 1 二进制文件: 1. 敏感数据(密码)与可供许多人访问的 src 代码分开存储 2. 如果 PRD 中出现错误,您可以使用该二进制文件并将其部署到其他地方重现和调试 3. 更少的时间和空间消耗 4. 如果环境配置更改 - 无需重新构建二进制文件(特别是如果您不想将最新代码与最新配置一起部署,这很尴尬) 5. 更简单构建脚本(尽管部署脚本会吸收这种复杂性) 6. 如果必须更改配置(而不是等待构建),可以快速做出反应 7. 等等,等等。

标签: java maven


【解决方案1】:

Environments-maven-plugin 提供了上面列出的所有东西。

Environments-maven-pluginmultienv-maven-plugin 的一个分支。 multienv-maven-plugin 的核心理念是src/main/environments目录下的每个目录都是一个环境,每个目录都会产生war。这种哲学太局限了。它以牺牲功能为代价提供了简单性。 Environments maven 插件继续使用 src/main/environments 中的目录作为各种环境的名称。但它进一步扩展了插件。下面列出了其中一些细节。

环境排除。

大多数项目都有用于各种环境的资源文件,以及用于在开发人员的机器上运行代码但指向各种环境的资源文件。例如:dev、dev_local、ci、ci_local、qa、qa_local 等——这些 QA 资源文件用于在 QA 环境中运行应用程序。 qa_local 资源文件用于在指向 QA 环境的开发人员机器上运行应用程序。运行发布版本时,不应生成 dev_local、ci_local 和 qa_local 的 war 文件。否则,它会减慢构建速度并使竹构建页面变得混乱,从而可能导致执行实际部署的一方感到困惑。

environments-maven-plugin 允许排除不希望生成 war 文件的环境。这可以使用插件配置中的 excludeEnvironments 标签来完成。

示例配置

<plugin>
   <groupId>net.sf.environments-maven-plugin</groupId>
   <artifactId>environments-maven-plugin</artifactId>
   <version>1.1.0-SNAPSHOT</version>
   <configuration>
      <excludeEnvironments>dev01, qa01 ,qa02,</excludeEnvironments>
      <parallel>true</parallel>
   </configuration>
   <executions>
      <execution>
         <goals>
            <goal>configuration</goal>
         </goals>
      </execution>
   </executions>
</plugin>

不允许清单自定义

当为不同的环境生成war文件时,可能存在需要添加特定于环境的清单条目的情况。使用插件配置中的 environmentArchiveConfiguration 标记,可以使用 environment-maven-plugin 轻松完成此操作。

您可以为所有环境设置一个配置,也可以为每个单独的环境设置一个配置,如下所示。

为方便起见,环境已添加到每个 war 文件中。清单条目如下所示。

<plugin>
         <groupId>net.sf.environments-maven-plugin</groupId>
         <artifactId>environments-maven-plugin</artifactId>
         <version>1.1.0-SNAPSHOT</version>
         <configuration>
            <excludeEnvironments>dev01, qa01</excludeEnvironments>
            <parallel>true</parallel>
            <archives>
               <environmentArchiveConfiguration>
                  <environment>dev02</environment>
                  <archive>
                     <manifestEntries>
                        <mode>development</mode>
                        <key>value</key>
                     </manifestEntries>
                  </archive>
               </environmentArchiveConfiguration>
               <environmentArchiveConfiguration>
                  <environment>prod01, prod02</environment>
                  <archive>
                     <manifestEntries>
                        <mode>development1</mode>
                        <key>value1</key>
                     </manifestEntries>
                  </archive>
               </environmentArchiveConfiguration>
            </archives>
         </configuration>
         <executions>
            <execution>
               <goals>
                  <goal>configuration</goal>
               </goals>
            </execution>
         </executions>
      </plugin>

环境特定过滤

environments-maven-plugin 引入了commonDirfilters 标签。 commonDir 标记采用src/main/environnments 内的目录路径。 common 目录包含所有环境通用的模板。这些模板可以包含由@ (@variable@) 括起来的变量。

过滤器标签可以有多个过滤器标签。每个过滤器标签都采用一个文件的名称。

构建战争时,插件会执行以下操作。

  • 从公共目录中获取模板文件。
  • 从环境中检索具有在过滤器标记中声明的名称的文件 目录。例如,如果当前正在构建开发战,则 插件尝试从过滤器标签中查找文件 src/main/environments/dev 目录。
  • 将过滤标签中所有文件的所有键值对合并到一个HashMap中。
  • 使用 HashMap 中的键值对替换 模板。
  • 将上一步中的文件打包到 dev war 文件中。
  • 还打包了 src/main/environments/${env} 目录下的所有文件。

示例配置

<plugin>
   <groupId>net.sf.environments-maven-plugin</groupId>
   <artifactId>environments-maven-plugin</artifactId>
   <version>1.3.0-SNAPSHOT</version>
   <configuration>
      <commonDir>common</commonDir>
      <filters>
         <filter>ec.properties</filter>
      </filters>
   </configuration>
   <executions>
      <execution>
         <goals>
            <goal>environment</goal>
         </goals>
      </execution>
   </executions>
</plugin>

下图说明了文件/目录命名/结构。

注意:为了使过滤起作用,commonDir 和 filters 标记都应该被声明。

将资源文件放置在 War 文件内的特定目录中的功能

资源文件通常属于war文件内的WEB-INF/classes目录。要在 multimaven-maven-plugin 中实现这一点,必须在 src/main/environments 中的每个环境中创建 WEB-INF/classes 目录,然后将资源文件放入其中。如下所示,这是多余且丑陋的。

    • 主要
      • 环境
        • 开发
          • WEB-INF
              • 文件
        • dev_local
          • WEB-INF
              • 文件
          • WEB-INF
              • 文件
        • ci_local
          • WEB-INF
              • 文件

为了解决这个问题,environments-maven-plugin 引入了一个名为 targetPath 的新标签。如果这个标签声明了一个目录路径作为值,那么打包在war中的资源文件被放置在目录中。所以。它看起来像这样。

  • app_dev.jar
    • WEB-INF
        • 文件
  • app_dev_local.jar
    • WEB-INF
        • 文件
  • app_ci.jar
    • WEB-INF
        • 文件
  • app_ci_local.jar
    • WEB-INF
        • 文件

所以在这种情况下目录结构看起来像这样。

    • 主要
    • 环境
      • 开发
        • 文件
      • dev_local
        • 文件
        • 文件
      • ci_local
        • 文件

示例配置

<plugin>
   <groupId>net.sf.environments-maven-plugin</groupId>
   <artifactId>environments-maven-plugin</artifactId>
   <version>1.1.0-SNAPSHOT</version>
   <configuration>
      <targetPath>WEB-INF/classes</targetPath>
   </configuration>
   <executions>
      <execution>
         <goals>
            <goal>environment</goal>
         </goals>
      </execution>
   </executions>
</plugin>

构建单一环境

multienv-maven-plugin 不提供构建单一环境的工具。结果是,一个人将不得不为单独的环境维护一个完全独立的设置。 environment-maven-plugin 使用命令行选项-Dem.env 解决了这个问题。该选项的值是src/main/environment中感兴趣的环境的目录名。

mvn clean install -Dem.env=dev_local

资源

项目页面https://sourceforge.net/projects/environments-maven-plugin/

源代码https://sourceforge.net/p/environments-maven-plugin/code/ci/master/tree/

概览页面https://environments-maven-plugin.sourceforge.io/index.html

编辑

这就是https://12factor.net/config 所说的关于配置的内容。

Apps sometimes store config as constants in the code. This is a violation of twelve-factor, which requires strict separation of config from code. Config varies substantially across deploys, code does not.

environments-maven-plugin 支持将配置与代码分离。

Another aspect of config management is grouping. Sometimes apps batch config into named groups (often called “environments”) named after specific deploys, such as the development, test, and production environments in Rails. This method does not scale cleanly: as more deploys of the app are created, new environment names are necessary, such as staging or qa. As the project grows further, developers may add their own special environments like joes-staging, resulting in a combinatorial explosion of config which makes managing deploys of the app very brittle.

请注意,它建议为不同的环境维护单独的属性文件是脆弱的,但不建议任何替代方案。虽然知识渊博的人可以争论这种想法的优点和缺点,但在现实世界中,属性文件被分组到各种环境中。在这种情况下,需要将这些组正确打包到战争文件中或将这些组直接交付到各自的环境中,并希望进行部署的人没有无知的恳求和政治游戏。 environment-maven-plugin 采用将资源文件打包成war,生成多个war的方式。一旦发生战争,CI 服务器就可以接管部署的责任。无需担心将文件放置在服务器上的适当位置或创建环境变量。如果这个问题有一个规范的解决方案,很高兴知道。

还请注意,它并没有说明要创建多场战争。


请注意,没有规定使建议的解决方案无效的规范方法。

1.) 您不应将密码存储在文本文件中。公认的做法是将它们存储在服务器上的环境变量中。但可能有更安全的方法。

2.) 构建多个战争并不比构建单个战争更不可靠,假设 java 和 maven 版本相同。当我们使用特定版本的 java 和 maven 时,不言而喻的假设是,给定一段代码,构建的多次迭代将产生完全相同的战争。

3.) 不应将部署到生产环境的战争作为唯一的事实来源。那是单点故障。相反,使用发布分支来管理正在发布的代码将确保您有一个可以持续重新生成的战争。如果战争文件被损坏、意外删除等,这可以为您省去麻烦。

4.) 重现生产缺陷的通常做法是在本地机器上运行发布分支。没有获得部署在生产环境中的战争副本。

5.) 当一个人无限期地保存这些文件时,空间可能是一个问题。

6.) 使用这个插件构建所有的战争肯定很慢。但这应该在它自己的 Maven 配置文件中。该配置文件应在 CI 服务器上执行。一个人应该只在本地机器上为单个环境构建战争文件。插件可以实现这一点。

如果 Tn= 构建 n 次战争所花费的时间远少于 T1=建立一场战争所花费的时间 那么用这个插件 (Tn) 比 (n * T1) 少很多

7.) 除非在某人的车库或地下室工作,否则极不可能允许在 Java 世界中更改生产中的任何内容。但是,如果您认为自己喜欢在生产中随意更改配置文件的灵活性,那么这个插件不允许这样做。只知道这会引入任意性。即无法保证您交付到生产环境的文本文件与当前生产环境中的文本文件相同。

因此,总而言之,考虑到过去三个月采取的方法并没有明显失效甚至破坏,可以肯定地假设构建多个战争与单独发送配置文件一样可以接受。这仅取决于人们喜欢什么,是对公认做法的宗教坚持,还是一种更简单的方法,无需以支持或其他形式提供中介。

【讨论】:

  • 除了这里的 12 因素想法之外,这些更改正是使其处理比所需更复杂的原因..
  • 关于您的编辑:为什么不能自动部署单独的属性文件?我真的看不出有什么区别。
  • > 为什么不能自动部署单独的属性文件?真正的问题是它们是否可以适用于所有情况。我可以告诉你,他们不可能处于我的境地。我们的生产服务器运行在由两个不同团队维护的 windows 和 unix 服务器上。我只是一个开发人员,所以不要问我为什么他们是这样的。 Windows 部署是自动化的,而 unix 部署是手动的。如果您的论点是他们没有正确设置我所在的位置,那是我从事的大部分项目,即现实世界。
  • @ShaggyInjun 对不起,如果这些 cmets 似乎是敌对的。他们本不该如此。开发一个 Maven 插件来解决您公司的问题是完全可以的(我们还为此创建了一些 Maven 插件)。我只是不确定是否应该为这种方法进行宣传。如果有人来 stackoverflow 了解他/她应该如何处理不同阶段的属性文件,我会建议他/她将它们与战争文件分开。
猜你喜欢
  • 1970-01-01
  • 2013-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-01
相关资源
最近更新 更多