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?
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.
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.
web. exposure. include=refresh: this is actuator property which will help us to refresh the properties without restarting the server.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With