Parent pom and microservices

后端 未结 6 1166
礼貌的吻别
礼貌的吻别 2020-12-14 16:23
  • We have several projects that are microservices, every project is independent (running on separate spring boot server, exposing rest services, using separate DB schema
相关标签:
6条回答
  • 2020-12-14 17:03

    I would avoid dependencies in the parent pom. It's awkward if one of your (independent) microservices would want some other things. It's weird to have the parent know of each microservice.

    You can stick with dependencyManagement though to suggest default versions/scopes if you want. A parent pom is, non the less, very convenient to define plugins, repositories and the like.

    Instead, I would group a common set of dependencies into a specific artifact(s), that may be only a single pom with dependencies. Then you can depend on, say "com.example/common-db-dependencies/1.2" to include a standard set of database dependencies, like hibernate, apache derby and JPA specs. (or whatever you're using). A service does not use JPA/SQL could avoid that dependency all together.

    Don't entangle yourself though. It's easy to overwork dependency structures if you're trying to cover each case. So, only try to standardize things that really get used by a majority of the services.

    0 讨论(0)
  • 2020-12-14 17:04

    Here there is one issue with dependency and dependency management. Say one of your micro service wants to upgrade to newer version of common for some reason...you cant do that as you have parent. I do understand temptation of reducing duplication of redundant things like plugin configuration. In micro service we need to think more about independence of each service.

    Some config like say your repository or release configuration etc can be common.

    0 讨论(0)
  • 2020-12-14 17:16

    Most books on microservice architecture recommend autonomy as a principle. Using a parent pom violates that principle.

    First of all with a parent pom you can no longer adopt a polyglot approach and write your microservices in different languages.

    You'll also be forced to use the dependencies prescribed by the parent, especially if the enforcer plugin is employed.

    The microservices will no longer be independently deployable.

    There is also the risk that your work on any one microservice may break others if that work involves altering the parent.

    0 讨论(0)
  • 2020-12-14 17:20

    The 'problem' with a multi-module parent pom is that, without complicated profiles, it locks the modules in the same release cycle (assuming you're using the Release Plugin, which you should be).

    The way I work with Maven is to have a parent pom that declares:

    • common dependencies (logging APIs, JUnit, etc).
    • common plugins.
    • all dependencies in the dependencyManagement section.
    • all plugins in the pluginManagement section.

    Each module delcares the parent pom as its parent but the parent knows nothing about the modules.

    The benefit of this comes from the last to two bullets above, the 'management' sections. Anything contained in a 'management' section needs to be redeclared in a module that wants to use a particular dependency or plugin.

    For example the parent might look like this:

    <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>
    

    And the module might look like this:

    <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>
    

    The module would:

    • have dependencies on org.slf4j:slf4j-api:1.7.7:compile, junit:junit:4.11:test and commons-lang:commons-lang:2.6:compile.
    • has the plugin org.apache.maven.plugins:maven-assembly-plugin:2.4
    0 讨论(0)
  • 2020-12-14 17:20

    I would definitely use a parent project.

    I've been working for years with both the structures...Microservices and not, modular or not, Ant, Maven and Gradle..

    We need to understand that using a parent pom does not mean talk about microservices not coupled and independent:

    • they can be still independent and not coupled using parent pom,
    • they can be still built release and updated in isolation even if you are using a parent pom.

    I heard saying "a microservice may need to use different versions for a dependency", well you can, just override the dependency in the specific microservice pom.

    We need to focus on "What are here the benefit and what are the cons":

    • Control and standardization: I can manage the common dependencies (with the dependencies management) in a single point, it makes easier to roll out dependencies changes across all the modules, yes we may need different third parties version, but same time we need to avoid losing control over all the dependencies, so exceptions may be allowed but they needs to be balanced with the "standardization"
    • Group management: I can still release just a single module, but I can also manage multi modules releases in a easier way, without having to release module by module, but simply the modules that are under development, in this case I still have a single entry point and all the common dependencies can be overviews withing the parent

    And much more:

    • common third parties and platform dependencies management
    • common third parties and platform standardization
    • Full control of the dependencies ecosystem withing the whole application (structured in micro services)
    • common plugins management and standardization
    • reduce duplication and redundant logic.
    • Configurations management and standardization
    • Easier maintenance, change in one place instead of potentially 30 places!!
    • easier to test and roll out common change.

    What about the cons? I don't see any for the moment, as exceptions can be managed through overriding common behaviour in the specific microservices pom, I can still manage anything in isolation (build in isolation, release in isolation, deploy in isolation..) There is nothing coupled

    Not sure yet what we mean with "it locks the modules in the same release cycle" It does not, unless you are using external SNAPSHOT, I can release a microservice in isolation re-using the same parent version.

    for example I can have module 1 declaring Parent 1.0 and be released in isolation without having to run the release process from the parent, I can run it directly on the submodule, but I need to not declare any external SNAPSHOT within the submodule project (you would have same issues with or without parent)

    0 讨论(0)
  • 2020-12-14 17:23

    A major drawback of using a parent pom approach with microservices is it will make the release management for microservices a slightly tricky affair. Few related pointers -

    • The parent pom should not be frequently changed, should be managed as a separate project in a separate repo.
    • Every change to the parent pom should increment the parent pom version. Once the changes are finalized, the parent pom repo should also be tagged. (treating is as a separate library with independent releases)
    • Moreover the child pom of all the microservices being touched should ideally be updated to point to the latest parent pom version (affecting the autonomy of microservices to some extent). This may also lead to forceful ask of upgrading the microservice to use newer versions of the libraries, which may not always be a feasible option.
    • Even if the only change in a microservice is to point to the new parent pom version, it would call for a new (mostly minor) version release of the service.

    Suggestions -

    • You can use the maven enforcer plugin to check for duplicate dependency versions specified between parent and child poms.
    • The parent pom will not be a good option for extensive dependencies and dependency-management, but can certainly be used for things like repositories, distribution management, and plugin management which shall generally not have clashes between microservices.
    0 讨论(0)
提交回复
热议问题