Automatic refresh of client configuration through bus mechanism
Schematic diagram
Using the webhook notification function of GIT service, after each configuration update, GIT server will call the / Actor / bus refresh interface of configuration center by post mode, and the bus service of configuration center will broadcast this event to all clients joining the bus, and the client will read the content of configuration center from the new after receiving the event.
Increase POM dependency
The service (spring cloud config server) and client (spring cloud config client) of the configuration center are all added to the spring cloud bus reference package:
org.springframework.cloud
spring-cloud-starter-bus-amqp
Start rabbitmq
docker pull rabbitmq:3-management
docker run -d --hostname my-rabbit --name rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
You can visit 127.0.0.1:15672/ log in to rabbitmq management monitoring background, and the user name and password are all guest / guest.
Modify configuration information
Both the spring cloud config server and the spring cloud config client in the configuration center need to modify the contents of the configuration file:
The application.properties of the spring cloud config server project is added:
#Turn on message tracking
spring.cloud.bus.trace.enabled=true
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#Exposed access points shown
management.endpoints.web.exposure.include=*
The application.properties of the spring cloud config client project is added:
#Turn on message tracking
spring.cloud.bus.trace.enabled=true
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#Exposed access points shown
management.endpoints.web.exposure.include=*
Add bootstrap.properties of spring cloud config client project (otherwise, an error will be reported: a component required a bean named ‘configserverretryinterceptor’ that could):
spring.cloud.config.fail-fast=true
Configure git’s webhook
192.168.0.21:9004/actor/bus-refresh is the address of my configuration center. If there are multiple configuration centers that can write multiple webhooks, it will be successful if 204 is returned during the test on the page.
Clear the body in webhook’s post request
When git requests webhood post, it will add such a load to the body by default. Spring boot cannot be parallelized. Therefore, in the spring cloud config server, create the following two classes:
This code refers to: spring cloud config configuration center and automatic hot load configuration with GitHub
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
//Empty the body in the request
public class EmptyRequestWrapper extends HttpServletRequestWrapper{
public EmptyRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public ServletInputStream getInputStream() throws IOException {
byte[] bytes = new byte[0];
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return byteArrayInputStream.read() == -1 ? true:false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
}
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(filterName = "bodyFilter", urlPatterns = "/*")
@Order(1)
//Git will add such a payload to the body by default when it makes a webhood post request. Spring boot cannot be parallelized.
public class BusRefreshFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
String url = new String(httpServletRequest.getRequestURI());
//Filter / Actor / bus refresh requests only
if (!url.endsWith("/bus-refresh")) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
//Using HttpServletRequest to wrap the original request to modify the body content in the post request
EmptyRequestWrapper requestWrapper = new EmptyRequestWrapper(httpServletRequest);
filterChain.doFilter(requestWrapper, servletResponse);
}
@Override
public void destroy() {
}
}
Finally, add @ servletcomponentscan annotation on the startup class
@SpringBootApplication
//Start configuration center
@EnableConfigServer
//Start service discovery
@EnableDiscoveryClient
@ServletComponentScan
public class SpringCloudConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConfigServerApplication.class, args);
}
}
Test auto refresh Auto
Access the client program 127.0.0.1:9006/configtest to get the current result test-8. Access the configuration center is also test-8:
We update the GIT reference to change the configuration to test-9:
Check the configuration center 127.0.0.1:9004 / configdepot / test, the content has been changed to test-9, and then refresh the client program 127.0.0.1:9006 / configtest. At this time, the configuration content has been successfully changed to test-9, and the bus event informs the client that the configuration is successfully refreshed.
The process of refreshing configuration information can also be seen from the logs of the server and client in the configuration center:
Source code
GitHub warehouse: https://github.com/sunweisheng/spring-cloud-example