Auto-refresh client configuration via bus mechanism (Consul,Spring Cloud Config,Spring Cloud Bus)

Posted by PerfecTiion on Mon, 30 Sep 2019 04:45:41 +0200

Auto-refresh client configuration via bus mechanism

Schema Diagram

With the webhook notification function of the Git service, after each configuration update, the Git server invokes the/actuator/bus-refresh interface of the Configuration Center by POST. The bus service of the Configuration Center broadcasts this event to all clients joining the bus, and the client reads the content of the Configuration Center from scratch when it receives the event.

Increase POM dependency

Both the server (spring-cloud-config-server) and client (spring-cloud-config-client) of the configuration center join the Spring Cloud Bus reference package:

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

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 access 127.0.0.1:15672/login rabbitmq administration monitoring background, the username password is guest/guest.

Modify configuration information

Both the server (spring-cloud-config-server) and the client (spring-cloud-config-client) of the configuration center need to modify the contents of the configuration file:
application.properties for the spring-cloud-config-server project increased:

# 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 Displayed
management.endpoints.web.exposure.include=*

application.properties for the spring-cloud-config-client project increased:

# 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 Displayed
management.endpoints.web.exposure.include=*

The bootstrap.properties for the spring-cloud-config-client project is increased (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/actuator/bus-refresh is the address of one of my configuration centers. If there are multiple configuration centers that can write multiple webhook s, returning 204 in the page test indicates success.

Empty the body in the POST request for Webhook

Git makes webhood post requests by default with such a payload on the body that Spring Boot cannot be parallelized, so create the following two new classes on the spring-cloud-config-server side of the configuration center:
This code refers to: spring_cloud config configuration center and automated hot load configuration using 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 Body in 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 makes a webhood post request with such a payload by default that 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/actuator/bus-refresh requests only
        if (!url.endsWith("/bus-refresh")) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        //Wrap the original request using HttpServletRequest to modify the body content in the post request
        EmptyRequestWrapper requestWrapper = new EmptyRequestWrapper(httpServletRequest);

        filterChain.doFilter(requestWrapper, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

Finally, add the @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, get the current result Test-8, access the Configuration Center is also Test-8:


We updated the Git reference to change the configuration to Test-9:


Check 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, when the configuration content has been successfully changed to Test-9, bus events notify the client that the configuration has been refreshed successfully.


The process of refreshing configuration information can also be seen from the logs of the configuration center's servers and clients:

Source code

Github repository: https://github.com/sunweisheng/spring-cloud-example

Topics: Java Spring RabbitMQ git github