Skip to main content

Microservices - Config management using Spring cloud bus and Rabbit MQ

In this tutorial we will learn how to add Rabbit MQ capabilities to our Spring cloud config server so any changes to configurations can be pushed to all connected applications during runtime. We need such kind of behaviour when we need to refresh the properties without restarting our application. Below is the overall architecture for this complete setup.
spring cloud bus

Spring Cloud Config Server

Spring cloud config server is used to setup the distributed configuration using GIT or local file system where we can keep our configuration files and serve as them from Spring cloud config server. Client application just has to connect with config server by providing their application and profile name for specific configuration. Please refer below link where I have explained more about cloud config and how to code it.
https://www.thetechnojournals.com/2019/10/spring-cloud-config.html

Install Rabbit MQ

Please refer below link on how to install rabbit-mq and virtual host verification.
https://www.thetechnojournals.com/2019/11/installing-rabbit-mq.html
Note: If there is any problem running the virtual host then your Spring config server may not be able to connect to rabbitmq and you will see similar error in Spring boot console.
c.r.c.impl.ForgivingExceptionHandler     : An unexpected connection driver error occured (Exception message: Socket closed)

Spring Cloud Bus

When we have changes to our configuration in GIT source repository then it may notify the config server for the changes and these changes can be pushed to all connected clients so that they can refresh the properties with latest available changes. It can be achieved through the webhook which is supported by many providers like github to publish the event in which users are interested. Then config server push the event to all clients through rabbitmq and all connected clients refresh the changes at runtime. Below changes are required to enable the spring cloud bus in spring cloud config server application which we have seen in first section "Spring Cloud Config Server".

Maven dependencies

We need to add below dependencies where monitor starter stream dependency is added to communicate with rabbit mq and config monitor is added to receive notifications from git repository.
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-monitor</artifactId>
        </dependency>

Configuration changes

Add below properties in your application.properties or application.yml to enable the Spring cloud bus with RabbitMQ.
spring:
  cloud:
    bus:
      enabled: true
  rabbitmq:
    host: localhost
    port: 5672
    virtual-host: /
    username: guest
    password: guest

Webhook configuration using Github

A webhook need to be configured using Github so it can notify our Spring cloud config server for any changes committed to the configuration repository. We configure the webhook in Github by registering our /monitor endpoint of config server application and due to this we should have public IP instead of localhost. See in next section how to refresh for localhost manually.
Refer the below screenshot for webhook configuration.
git webhook

Manual refresh using /monitor endpoint

 In case we don't have a public IP for our host where cloud config server application is running, we can auto refresh all the connected applications by hitting only one URL manually on cloud config server application.

Monitoring URL: http://localhost:8888/monitor
Please note that to access above URL you have to make a POST request with below headers and request body.
Headers:
 Content-Type: application/json
 X-Event-Key: repo:push
 X-Hook-UUID: webhook-uuid
Request body:
 {"push": {"changes": []}}
While executing above request, you may face similar error as given below due to the default enablement of csrf in spring.
{
    "timestamp": "2019-11-23T16:37:08.098+0000",
    "status": 403,
    "error": "Forbidden",
    "message": "Forbidden",
    "path": "/monitor"
}
To fix this issue we need to disable the csrf by creating below class.
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }
}

Config Test Service (Config client)

Now we will create a client application which will access the properties using cloud config server and refresh them without restarting it.

Maven Dependencies

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

bootstrap.yml

Add below properties to bootstrap properties or yml file.
spring:
  profiles:
    active: DEV
  cloud:
    config:
      name: microservices-config
      uri: http://localhost:8888/
      username: config_user
      password: config_user
  rabbitmq:
    host: localhost
    port: 5672
    virtual-host: /
    username: guest
    password: guest

PropertiesController.java

This class uses property key "message" which we will test with refresh event. We have used RefreshScope annotation on this class so it can be refreshed with all the message properties in this class.
@RefreshScope
@RestController
public class PropertiesController {
    @Value("${message}")
    private String message;

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public String testMessage(){
        return message;
    }
}

Testing the application

Below are the steps to test the application.

Other posts you may like

Microservice development using Spring boot
Spring cloud API gateway tutorial
Registry/ discovery server using Spring boot and Eureka

Comments