Realize automatic refresh of client configuration through bus mechanism (consul, spring cloud config, spring cloud bus)

Time:2019-11-30

Automatic refresh of client configuration through bus mechanism

Schematic diagram

Alt text

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

Alt text
Alt text
Alt text

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:
Alt text
Alt text
We update the GIT reference to change the configuration to test-9:
Alt text
Alt text
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.
Alt text
Alt text
The process of refreshing configuration information can also be seen from the logs of the server and client in the configuration center:
Alt text
Alt text

Source code

GitHub warehouse: https://github.com/sunweisheng/spring-cloud-example