Saturday, March 23, 2019

Microservices - Configuration Management

Greetings!

There were time we hard coded configuration properties directly into the code. When we get matured we learnt that it is always a better choice to remove hard coded values from the code and add them as configurable properties. That definitely paid off. For an example we add our database configuration in a separate file so that depending on the environment we can easily change it. We when use profiles we go one step further to add file per environment like dev, live, etc.

How will this effect to microservices architecture? If we are dealing with small number of microservices it is ok to bundle them with the corresponding jar though it is not the microservices way of doing things.

When number of the services are growing how do you maintain your environment? It will be a nightmare to keep a track of all properties in this way. Also, when we automate our release process it will be harder to do so.

This is why in microservices architecture we need to segregate all the service configurations. Application configurations will not bundle with the service instance, instead it will pick its configurations from a central location.

Say what, our microservices will be using another microservices to get their configuration properties!

By the way, how many times have you deployed into production environment with your development environment properties ;)

Complete Source Code

Do it in Spring way

Sure thing, we are using Spring framework with Spring Boot hence we use Spring Cloud Config.
This is what they say;
"Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With the Config Server you have a central place to manage external properties for applications across all environments."

Spring cloud config uses file location or github location as the configuration repository which makes maintenance very easy.


Let's create our configuration server


  1. Generate a project using https://start.spring.io
  2. Add spring-cloud-config-server as dependencies.
  3. @EnableConfigServer
  4. Add configuration repository path.
  5. Add configurations properties.

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

Boostrap class

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication

Application properties

Easiest way to add a file repository is using a file location. Let's create default and dev profiles in a file location. (mine is /home/manjula/config-repo)
Special thing to note here is we need to name file according to our service name.
<service_name>-<profile>.yml

myservice.yml
message: "Hello from default profile"

myservice-dev.yml

message: "Hello from development team"


Update the application.yml
server:
  port: 8888

spring:
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          searchLocations: file:///home/manjula/config-repo

Start the application and locate to http://localhost:8888/myservice/default
You should get this output.
{
    "name": "myservice",
    "profiles": [
        "default"
    ],
    "label": null,
    "version": null,
    "state": null,
    "propertySources": [
        {
            "name": "file:///home/manjula/config-repo/myservice.yml",
            "source": {
                "message": "Hello from default profile"
            }
        }
    ]
}

For the dev profile locate to http://localhost:8888/myservice/dev
// ommited
        {
            "name": "file:///home/manjula/config-repo/myservice-dev.yml",
            "source": {
                "message": "Hello from development team"
            }
        },
        {
            "name": "file:///home/manjula/config-repo/myservice.yml",
            "source": {
                "message": "Hello from default profile"
            }
        }
// ommited

Note that this gives both properties though when using in a client dev profile will override the values from the default profile.

Using a Git repository

Even though file location solution seems simple and easy, it will add additional problems when working with a team. Also, using a Git repository we can easily manage version history.
Instead of the file location, create a Git repository and commit our service's configuration properties.

Below is the updated application.yml
server:
  port: 8888

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/slmanju/microservices-demo
          searchPaths: configurations
          skipSslValidation: true

Re-start the server and you should get the same responses as before.

Config Client

Now our configuration server is up. We need to update our microservices to fetch the properties from configuration server.
Spring Boot uses bootstrap file early in the booting process. Hence we can add our service name and configuration service location into boostrap.yml file.

  1. Create and update bootstap.yml file.
  2. Add corresponding property/yml files into configuration repo.
  3. Update maven dependencies to add config-server.
  4. Run the application.

Note: Pay attention to this line;
Fetching config from server at : http://localhost:8888

bootstrap.yml

spring:
  application:
    name: catalog-service

  cloud:
    config:
      uri: http://localhost:8888

add maven dependency

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>



No comments:

Post a Comment