Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply /refresh on multiple instances annotated with @refreshScope

I'm writing spring boot application, which using spring configuration, deployed on pivotal cloud foundry and exposed by Netflix Eureka as discovery serivce / load balancer.

I have created a bean as followed:

@Component
@ConfigurationProperties("config")
@RefreshScope
@Data
public class GeneralProperties {
    private boolean ignoreEvent;
}

When calling to the application route that Eureka exposed with /refresh after changing the actual property in the configuration repository, the value that annotated by @refreshScope was changed (end in the response status the field exsiting), which means it's working correctly.

The issue starts when running multiple instances of the same application on the cloud, and calling to the /refresh.
The route that beeing used is the one that exposed by Eureka, which using it's load balancer to route the call to one of the available instances.

It leads to unexpected results that not all the instances are getting updated with the latest change in the property.

Any suggestions how to apply the change on all instances?

like image 472
yuval simhon Avatar asked Dec 25 '17 10:12

yuval simhon


People also ask

What is @RefreshScope annotation in spring boot?

Now, you need to add the @RefreshScope annotation to your main Spring Boot application. The @RefreshScope annotation is used to load the configuration properties value from the Config server.

How do I refresh application properties in spring boot?

For Reloading properties, spring cloud has introduced @RefreshScope annotation which can be used for refreshing beans. Spring Actuator provides different endpoints for health, metrics. but spring cloud will add extra end point /refresh to reload all the properties.

How do I reload the configuration properties without restarting the app?

web. exposure. include=refresh: this is actuator property which will help us to refresh the properties without restarting the server.


1 Answers

You should use Spring Cloud Bus in such a case. The idea behind this framework is to bind all your application instances to a topic in a message broker (RabbitMQ or Apache Kafka).

Add the following dependency to your pom.xml:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-bus-parent</artifactId>
            <version>1.3.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    </dependency>
</dependencies>

In the above example I added a dependency on amqp which is RabbitMQ. You'll also need to bind your application to the RabbitMQ, in PCF it's easy since it's built in to the platform.

When you need to refresh, you should invoke:

POST /bus/refresh

This would trigger an event to a topic that all instances of your application are listening to, and as a result - all instances would refresh their bean configuration.

Good luck.

like image 157
odedia Avatar answered Sep 28 '22 00:09

odedia