The book follows the text SpringCloud Config. If you haven’t seen it, you can take a look. In the last article, we mentioned the issue of configuration refresh. If we need to refresh the configuration, we need the client to perform refresh. We can use the Mechanism of Webhook to submit code and send requests every time to refresh the client. Spring Cloud Bus is the perfect solution to this problem.


I. Introduction to Spring Cloud Bus

Spring Cloud Bus connects distributed nodes through lightweight message brokers. This is used to broadcast state changes (such as configuration changes) or other message instructions. One of the core ideas of Spring Bus is to extend Spring Boot applications through a distributed initiator, which can also be used to establish a communication channel between multiple applications. Currently the only way to do this is to use the AMQP message broker as a channel, and the Settings for the same features (some of which depend on channel Settings) are in the documentation for more channels.

Ii. Solution

Solution a:

  • Spring Cloud Bus is widely translated as message bus in China. It can be understood as the management and dissemination of messages in all distributed projects, in fact, the dissemination of messages in distributed systems using MQ broadcast mechanism, currently commonly used Kafka and RabbitMQ. There are many things that can be done by using the mechanism of bus, among which configuration center client refresh is one of the typical application scenarios. We use a diagram to describe the mechanism used by bus in configuration center.

According to this figure, we can see the steps of using Spring Cloud Bus to do configuration update:

2. Client A receives requests to update the configuration from the Server and sends them to Spring Cloud Bus. 3 Other clients receive the notification and request the Server to obtain the latest configuration. 5. All clients obtain the latest configurationCopy the code

Scheme 2:

  • In scenario 1, we have reached the goal of using the message bus to trigger a client /actuator/bus-refresh and refresh all client configurations. But it’s not elegant. Here’s why:
Breaking the single responsibility of microservices. Microservices themselves are business modules that should not be responsible for configuration refreshes. The equivalence of each node of microservice is destroyed. There are certain limitations. For example, the network address of a microserver often changes during migration, and the WebHook configuration has to be modified in order to refresh automatically.Copy the code

So we changed the architectural pattern of Scenario 1 a little bit

At this time, the configuration update steps of Spring Cloud Bus are as follows:

The server receives the request and sends it to Spring Cloud Bus. 3. Spring Cloud Bus receives the message and notifies other clients. Request the Server to obtain the latest configuration. 5. All clients obtain the latest configurationCopy the code

Let’s take option two and transform our project so that we can make some changes to the server-side code to support bus/ Refresh

Three, the transformation of the server

  • Add RabbitMQ dependencies to the service terminal lovin-config-server. Here are the main POM dependencies after the transformation:
"Parent" > < artifactId > lovincloud < / artifactId > < groupId > com. Eelve. Lovincloud < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > < modelVersion > 4.0.0 < / modelVersion > < artifactId > lovin - config - server < / artifactId > < packaging > jar < / packaging > <name> LovinconfigServer </name> <version>0.0.1</version> <description> Configure server</ description> <dependencies> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> < groupId > DE. Codecentric < / groupId > < artifactId > spring - the boot - admin - starter - client < / artifactId > < version > 2.1.6 < / version > </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>Copy the code
  • Add rabbitMQ connection configuration
server:
  port: 8886   # Service port number
spring:
  application:
    name: lovinconfigserver     # service name
  security:
    basic:
      enabled: true
    user:
      name: lovin
      password: ${REGISTRY_SERVER_PASSWORD:lovin}
  cloud:
    config:
      server:
        git:
          uri: https://github.com/lovinstudio/lovincloud
          search-paths: lovin-config-repo
      label: master
  rabbitmq:
    host: 127.0. 01.
    port: 5672
    username: guest
    password: guest
eureka:
  client:
    serviceUrl:
      defaultZone: http://lovin:lovin@localhost:8881/eureka/   # Registered to eureka service address
Copy the code

Iv. Transform and configure the client

  • Add RabbitMQ dependencies to the service terminal project lovin-config-client. Here are the main POM dependencies after the transformation:
"Parent" > < artifactId > lovincloud < / artifactId > < groupId > com. Eelve. Lovincloud < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > < modelVersion > 4.0.0 < / modelVersion > < artifactId > lovin - config - client < / artifactId > < packaging > jar < / packaging > <name> LovinconfigClient </name> <version>0.0.1</version> <description> Configure the consumer </description> <dependencies> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> < groupId > DE. Codecentric < / groupId > < artifactId > spring - the boot - admin - starter - client < / artifactId > < version > 2.1.6 < / version > </dependency> <! -- <dependency>--> <! -- <groupId>org.springframework.cloud</groupId>--> <! -- <artifactId>spring-cloud-config-server</artifactId>--> <! -- </dependency>--> <dependency> <groupId>org.springframework.cloud</groupId> < artifactId > spring - the cloud - starter - config < / artifactId > < version > 2.1.3. RELEASE < / version > < / dependency > < the dependency > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>Copy the code
  • Add the configuration to connect to RabbitMQ
  1. Modify bootstrap.yml to add the configuration to connect rabbitMQ
server:
  port: 8807   # Service port number
spring:
  application:
    name: lovinconfigclient     # service name
  security:
    basic:
      enabled: true
    user:
      name: lovin
      password: ${REGISTRY_SERVER_PASSWORD:lovin}
#eureka:
# client:
# serviceUrl:
# defaultZone: http://lovin:lovin@localhost:8881/eureka/
  rabbitmq:
    host: 127.0. 01.
    port: 5672
    username: guest
    password: guest
Copy the code
  1. Modify application.yml to enable message tracing
spring:
  cloud:
    config:
      name: lovin-config
      profile: dev
      #uri: http://localhost:8886/
      #label: master
      discovery:
        enabled: true
        service-id: lovinconfigserver
    bus:
      trace:
        enabled: true
eureka:
  client:
    serviceUrl:
      defaultZone: http://lovin:lovin@localhost:8881/eureka/   # Note that the registry configuration needs to be moved to this file when it is highly available, but will not be read in application.yml

Copy the code

Five, start the test

  • 1. Start lovin-Eureka-server, Lovin-econfig – Server, and Lovin-econfig -client in sequence
  • 2. View the lovin-econfig-server to query the configuration

  • 3. View the lovin-econfig-client to query the configuration

  • 4. Modify the configuration and submit the token value from Lovin to LovinUpdate

  • 5. View the lovin-econfig-server configuration again

  • 6. View the lovin-econfig-client to query the configuration

  • Refresh the message bus

Because of API changes, the URL changes from /bus/refresh to /bus-refresh

  • 8. View the lovin-econfig-client to query the configuration

We can see that the refresh has been successful and that the message bus configuration is now complete

Land and local refresh

In some scenarios (such as grayscale publishing), we may only want to refresh the configurations of some microservices. In this case, the destination parameter of /actuator/bus-refresh endpoints can be used to locate the applications to be refreshed.

  • For example: / physical/bus – refresh? Destination =customers:8000, so that the microservice instance on the message bus determines whether to refresh based on the value of the Destination parameter. Customers :8000 refers to the ApplicationContext ID of each micro-service. The Destination parameter can also be used to locate specific microservices.
  • For example: / physical/bus – refresh? Destination = Customers :**, which triggers a configuration refresh for all instances of the Customers micro service.

  • Finally, the source code for this blog is welcome to this set of SpringCloud practices