CodeGym /Courses /Module 5. Spring /Lecture 224: Dynamic Configuration Updates in Microservic...

Lecture 224: Dynamic Configuration Updates in Microservices

Module 5. Spring
Level 23 , Lesson 3
Available

Today we'll answer that question and learn how to apply dynamic configuration updates in real time. Get your keyboards ready!


The problem with static configurations in microservices

Imagine you're the admin of a huge microservices zoo (yep, our favorite metaphor). For example, dozens of microservices depend on the same parameter, say, a limit on operation execution. That limit is stored in a centralized configuration, but what happens if you need to update it?

  1. You change the value in the storage (for example, in Git).
  2. Then you restart each microservice so it can pick up the new value.

Sounds like a pain. Especially when there are dozens or hundreds of services. Restarting is not only inconvenient, it can cause downtime. And if the parameter changes often? Then it's not just a pain — it's a full-blown disaster.

To avoid this, we need dynamic configuration updates. They let you apply changes on the fly, without restarting microservices. That's where the magic of Spring Cloud Bus comes in.


Spring Cloud Bus: the basics

Spring Cloud Bus is a tool for sending messages between microservices using a message broker like RabbitMQ or Apache Kafka. It lets you:

  • Distribute configuration changes across microservices.
  • Notify system components about changes.
  • Implement event-driven approaches to manage settings.

Example workflow

  1. An admin changes the configuration in Git (or another store).
  2. Spring Cloud Config Server detects the change and publishes an event to the message broker.
  3. All subscribed microservices receive the event and automatically refresh their configurations.

Approaches to dynamic config updates

Dynamic configuration updates in Spring are implemented using a few key pieces:

  1. Spring Cloud Bus for delivering configuration change events.
  2. The @RefreshScope annotation for refreshing beans that depend on configuration.
  3. Calling a REST endpoint to refresh beans — if you want to do it manually.

Let's talk about each one.


Spring Cloud Bus in action

Spring Cloud Bus uses message brokers (RabbitMQ, Kafka) to deliver events. In our case we'll use RabbitMQ (it's easy to integrate and widely used).

The step-by-step flow looks like this:

  1. Spring Cloud Config Server publishes a configuration change event.
  2. Spring Cloud Bus forwards that event to subscribers (your microservices).
  3. Subscribers receive the event and update their settings in real time.

Installing RabbitMQ is a separate task, but if you haven't set it up yet you can quickly spin it up with Docker:

docker run -d --hostname rabbitmq --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:management

Using the @RefreshScope annotation

The @RefreshScope annotation is your go-to tool for updating dependencies. If you have a bean that reads values from configuration, adding @RefreshScope to that bean will make sure it gets refreshed when those values change.

Here's an example:


@RestController
@RefreshScope
public class ConfigController {

    @Value("${example.config.value}")
    private String exampleConfig;

    @GetMapping("/config")
    public String getConfigValue() {
        return this.exampleConfig;
    }
}

If the example.config.value parameter changes, the bean will automatically pick up the updated value after the configuration update event.

Note that @RefreshScope only works with beans managed by Spring. If a bean is created manually (for example, with new), don't expect miracles.


Calling the REST endpoint to refresh configs

For a microservice to realize the configuration changed, you either wait for the Spring Cloud Bus event or manually call the /actuator/refresh endpoint. You need to enable this endpoint in the settings:

management.endpoints.web.exposure.include=refresh

For testing you can use curl:

curl -X POST http://localhost:8080/actuator/refresh

After calling /refresh, all beans annotated with @RefreshScope will be refreshed, and their updated parameters will be pulled in.


Hands-on: setting up Spring Cloud Bus

Let's try setting this up in a real environment. We'll create two microservices (a Config Server and a Service) that integrate with Spring Cloud Bus via RabbitMQ.

Step 1: Configure Spring Cloud Config Server

Create a new Spring Boot project (for example, via Spring Initializr) and add the dependencies:


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

Enable the Config Server in code:


@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

Configure application.yml:


spring:
  cloud:
    config:
      server:
        git:
          uri: https://your-repo-url
  rabbitmq:
    host: localhost
    port: 5672

management:
  endpoints:
    web:
      exposure:
        include: "*"

Run the server and check that it's working.


Step 2: Configure the microservice (client)

Create a second project and add the dependencies:


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

Configure bootstrap.yml to connect to the server:


spring:
  application:
    name: client-service
  cloud:
    config:
      uri: http://localhost:8888
  rabbitmq:
    host: localhost
    port: 5672

Add a controller with dynamic configuration:


@RestController
@RefreshScope
public class TestController {

    @Value("${example.config.value:default}")
    private String configValue;

    @GetMapping("/current-config")
    public String getConfigValue() {
        return configValue;
    }
}

Step 3: Testing dynamic updates

  1. Change the configuration in Git.
  2. Run this command on the Config Server:

curl -X POST http://localhost:8888/actuator/bus-refresh

Thanks to Spring Cloud Bus, updated values will appear in the microservices automatically.


Now you have a working setup that updates configurations in real time. Using Spring Cloud Bus makes managing settings in distributed systems way easier, and lets you sleep peacefully knowing that restarting microservices is a thing of the past.

Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION