父pom和微服务

时间:2015-01-09 16:45:49

标签: java maven microservices

  • 我们有几个微服务项目,每个项目都是独立的(在单独的Spring启动服务器上运行,暴露其他服务,使用单独的数据库架构......)
  • 我们使用maven来管理依赖项。

让父pom将每个微服务声明为模块是一个好主意吗?所以有助于管理公共依赖项(比如在每个项目中使用lib servlet-api,删除所有项目并仅在父pom中声明它)

6 个答案:

答案 0 :(得分:12)

问题'使用多模块父pom是这样的,没有复杂的配置文件,它会在相同的发布周期中锁定模块(假设你正在使用Release Plugin,你应该这样做。)

我使用Maven的方式是让父pom声明:

每个模块都将父pom作为其父级,但父级对模块一无所知。

这样做的好处来自上面的最后两个子弹,“管理”和“管理”。部分。 “管理”中包含的任何内容section需要在想要使用特定依赖项或插件的模块中重新声明。

例如,父级可能如下所示:

<project>

  <groupId>com.example</groupId>
  <artifactId>parent</artifactId>
  <version>1.0.00-SNAPSHOT</version>

  ...

  <dependencies>

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.7</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>            

  </dependencies>

  <dependencyManagement>

    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.6</version>
    </dependency>        

    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>2.1</version>
    </dependency>

  </dependencyManagement>

  <plugins>

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>

  <plugins>

  <pluginManagement>

    <plugins>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.4</version>
        <configuration>
          <appendAssemblyId>false</appendAssemblyId>
          <descriptors>
            <descriptor>src/main/assembly/assembly.xml</descriptor>
          </descriptors>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

    </plugins>

  </pluginManagement>

</project>

模块可能如下所示:

<project>

  <parent>
    <groupId>com.example</groupId>
    <artifactId>parent</artifactId>
    <version>1.0.00-SNAPSHOT</version>
  </parent>

  <groupId>com.example</groupId>
  <artifactId>module</artifactId>
  <version>1.0.00-SNAPSHOT</version>

  <dependencies>

    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>          
    </dependency>        

  </dependencies>

  <plugins>

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-assembly-plugin</artifactId>
    </plugin>

  </plugins>

</project>

该模块将:

  • 依赖于org.slf4j:slf4j-api:1.7.7:compilejunit:junit:4.11:testcommons-lang:commons-lang:2.6:compile
  • 有插件org.apache.maven.plugins:maven-assembly-plugin:2.4

答案 1 :(得分:4)

我会避免在父pom中依赖。如果你的(独立)微服务之一需要其他一些东西,那就太尴尬了。让父母知道每个微服务是很奇怪的。

如果需要,您可以坚持使用dependencyManagement建议默认版本/范围。无论如何,父pom非常便于定义插件,存储库等。

相反,我会将一组共同的依赖项组合到一个特定的工件中,这些工件可能只是一个具有依赖关系的pom。然后你可以依赖,比如说“com.example / common-db-dependencies / 1.2”来包含一组标准的数据库依赖项,比如hibernate,apache derby和JPA specs。 (或者你正在使用的任何东西)。服务不使用JPA / SQL可以避免所有依赖。

不要纠缠自己。如果你试图覆盖每个案例,那么过度依赖结构很容易。因此,只能尝试标准化大多数服务真正使用的东西。

答案 2 :(得分:4)

这里存在依赖和依赖管理的一个问题。假设你的一个微服务想要因某种原因升级到更新版本的公共...你不能这样做,因为你有父母。我确实理解减少插件配置等冗余重复的诱惑。在微服务中,我们需要更多地考虑每项服务的独立性。

有些配置说您的存储库或发布配置等可能很常见。

答案 3 :(得分:1)

大多数有关微服务架构的书籍都建议将自治作为一项原则。使用父pom违反了该原则。

首先,如果没有父pom,就不能 不再采用多语言方法,并用不同的语言编写微服务。

您还将被迫使用父母规定的依赖关系,尤其是在使用了强制执行器插件的情况下。

微服务将不再可独立部署。

如果在任何一项微服务上的工作都涉及更改父项,那么您的工作也可能会破坏其他服务。

答案 4 :(得分:1)

将父pom方法与微服务一起使用的主要缺点是,它将使微服务的发布管理变得有些棘手。很少有相关的指针-

  • 父pom不应经常更改,应在单独的仓库中作为单独的项目进行管理。
  • 对父pom的每次更改都应增加父pom的版本。更改完成后,还应标记父pom repo。 (处理是作为具有独立发行版的独立库)
  • 此外,理想情况下,应该将所有被触摸的微服务的子pom更新为指向最新的父pom版本(在某种程度上影响微服务的自治性)。这也可能导致强烈要求升级微服务以使用较新版本的库,但这可能并不总是可行的选择。
  • 即使微服务中的唯一更改是指向新的父pom版本,它也会要求该服务的新(主要是次要)版本发布。

建议-

  • 您可以使用Maven强制执行器插件检查父Pom和子Pom之间指定的重复依赖项版本。
  • 对于广泛的依赖项和依赖项管理,parent pom并不是一个好的选择,但是肯定可以用于存储库,分发管理和插件管理之类的东西,这些服务通常不会在微服务之间发生冲突。

答案 5 :(得分:0)

我肯定会使用父项目

我已经在这两种结构上工作了多年了……而不是微服务,无论是模块化还是非模块化,Ant,Maven和Gradle ..

我们需要了解,使用父pom并不意味着要谈论没有耦合和独立的微服务:

  • 它们仍然可以独立,并且不使用父pom耦合,
  • 即使您使用的是父pom,也可以单独构建并发布和更新它们。

我听说说“微服务可能需要对依赖项使用不同的版本”,您可以在特定的微服务pom中覆盖该依赖项。

我们需要关注“什么是好处和什么是缺点”:

  • 控制和标准化:我可以单点管理常见的依赖项(使用依赖项管理),这使得在所有模块中推出依赖项更改更加容易,是的,我们可能需要不同的第三项各方版本,但与此同时,我们需要避免失去对所有依赖项的控制,因此可以允许例外,但需要与“标准化”保持平衡
  • 组管理:我仍然可以只发布一个模块,但是我也可以通过一种更简单的方式来管理多个模块的发布,而不必逐个模块地发布,而只需发布下面的模块开发,在这种情况下,我仍然只有一个入口点,所有常见的依赖项都可以与父项一起作为概览

更多:

  • 常见的第三方和平台依赖项管理
  • 常见的第三方和平台标准化
  • 对依赖生态系统的完全控制以及整个应用程序(在微服务中构建)
  • 常用插件管理和标准化
  • 减少重复和冗余逻辑。
  • 配置管理和标准化
  • 维护更容易,只需将一个位置更改为30个位置即可!
  • 更容易测试和推出常见更改。

缺点如何? 我暂时看不到任何东西,因为可以通过覆盖特定微服务pom中的常见行为来管理异常,所以我仍然可以隔离管理任何内容(隔离构建,隔离发布,隔离部署..) 没有耦合

还不确定“ 它将模块锁定在相同的发布周期中”是什么意思,除非您使用的是外部SNAPSHOT,否则我可以隔离地释放微服务,重新使用相同的父版本。

例如,我可以让模块1声明Parent 1.0,并且可以独立发布而不需要从父级运行发布过程,我可以直接在子模块上运行它,但是我不需要在子模块中声明任何外部SNAPSHOT项目(无论有没有父母,您都会遇到同样的问题)