11, SpringCloud Bus message bus for SpringCloud microservices

Posted by fibonacci on Sat, 01 Jan 2022 19:17:43 +0100

SpringCloud Bus message bus

1. General

1.1 what is it

SpringCloud Bus can be used with Springcloud Config to dynamically refresh the configuration

It is a framework used to link the nodes of distributed system with lightweight message system. It integrates the event processing mechanism of Java and the function of message middleware.

Spring cloud Bus supports two message brokers: RabbitMQ and kafka

1.2 what can I do

Spring Cloud Bus can manage and propagate messages between distributed systems, just like a distributed actuator. It can be used to broadcast state changes, push events, etc. it can also be used as a communication channel between microservices

1.3 why is it called bus

  • What is a bus:
    In microservice architecture systems, lightweight message brokers are usually used to build a common message topic and connect all microservice instances in the system. Since the messages generated in this topic will be monitored and consumed by all instances, it is called message bus. Each instance on the bus can easily broadcast some messages that need to be known by other instances linked to the subject line.
  • Basic principle:
    ConfigClient instances listen to the same topic in MQ (SpringcloudBus by default). When a service refreshes data, it will put this information into the topic, so that other services listening to the same topic can be notified, and then update their own configuration.

2. RabbitMQ environment configuration

reference resources: https://blog.csdn.net/zhou_zhao_xu/article/details/119378590

3. Spring cloud bus dynamically refreshes global broadcast

3.1 demonstrate the broadcast effect and increase the complexity. Take 3355 as the template and create cloud config center3366 configuration center service module in the parent project

1. Modify pom file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.zzx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-center3366</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- config  -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

        <!-- eureka client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>com.zzx</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

2. Write bootstrap Yaml profile

server:
  port: 3366

spring:
  application:
    name: cloud-config-client
  cloud:
    # config client configuration
    config:
      label: master # Branch name
      name: config # Profile name
      profile: dev # Suffix
      uri: http://localhost:3344 # configuration center address

eureka:
  instance:
    instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port} # Set instance access address
    prefer-ip-address: true # Set the access path to display the ip address
  client:
    # Indicates that you are registered with Eureka Server. The default value is true
    register-with-eureka: true
    # Whether to retrieve your existing registration information from Eureka Server. The default value is true.
    # Single node doesn't matter. The cluster must be set to true to use load balancing with ribbon
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

# Exposure monitoring endpoint
management:
  endpoints:
    web:
      exposure:
        include: "*"

3. Write the main startup class

@SpringBootApplication
@EnableEurekaClient
public class MainConfigCenter3366 {
    public static void main(String[] args){
        SpringApplication.run(MainConfigCenter3366.class,args);
    } 
}

4. Write test controller

@RestController
@RefreshScope
public class ConfigClientController {

    @Value("${server.port}")
    private String serverPort;

    @Value("${config.info}")
    private String configInfo;

    @Value("${config.message}")
    private String message;

    @GetMapping("/configInfo")
    public String getConfigInfo() {
        return "serverPort: " + serverPort + "\t\n\n" + configInfo + "\t\n\n" + message;
    }
}

3.2 design idea

  1. Use the message bus to trigger one client / bus/refresh and refresh all clients

  2. Use the message bus to trigger the / bus/refresh endpoint of a server ConfigServer and refresh the configuration of all clients

  3. The architecture in Figure 2 is obviously more suitable. The reasons why Figure 1 is not suitable are as follows

  • It breaks the single responsibility of microservices, because microservices are business modules and should not undertake the responsibility of configuration refresh
  • It breaks the equivalence of micro service nodes
  • There are certain limitations. eg: when migrating a microservice, its network address often changes. At this time, if you want to refresh automatically, you will add more modifications

3.3 add message bus support to the server of 3344 configuration center

Modify pom add dependency

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

		<!-- Add message bus RabbitMQ support -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

Modify yaml configuration

server:
  port: 3344
spring:
  application:
    name: cloud-config-center # Microservice name registered into Eureka server
  cloud:
    config:
      server:
        git:
          username: zhouzhxu
          password: zzx.@10092111
          uri: https://github. com/zhouzhxu/springcloud-config. Git # git warehouse address on GitHub
          # uri: git@github.com:zhouzhxu/springcloud-config.git # Password free login is required
          # search for directory
          search-paths:
            - springcloud-config
          # Read branch
          default-label: master
  # rabbitmq related configuration
  rabbitmq:
    host: 47.107.124.79
    port: 5672
    username: admin
    password: admin

eureka:
  instance:
    instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port} # Set instance access address
    prefer-ip-address: true # Set the access path to display the ip address
  client:
    # Indicates that you are registered with Eureka Server. The default value is true
    register-with-eureka: true
    # Whether to retrieve your existing registration information from Eureka Server. The default value is true.
    # Single node doesn't matter. The cluster must be set to true to use load balancing with ribbon
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

# Exposed bus refresh configured endpoint
management:
  endpoints:
    web:
      exposure:
        include: 'bus-refresh'

3.4 add message bus support to 3355 configuration center client

Modify pom add dependency

		<!-- Add message bus RabbitMQ support -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

Modify bootstrap yaml

server:
  port: 3355

spring:
  application:
    name: cloud-config-client
  cloud:
    # config client configuration
    config:
      label: master # Branch name
      name: config # Profile name
      profile: dev # Suffix
      uri: http://localhost:3344 # configuration center address
  # rabbitmq related configuration
  rabbitmq:
    host: 47.107.124.79
    port: 5672
    username: admin
    password: admin

eureka:
  instance:
    instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port} # Set instance access address
    prefer-ip-address: true # Set the access path to display the ip address
  client:
    # Indicates that you are registered with Eureka Server. The default value is true
    register-with-eureka: true
    # Whether to retrieve your existing registration information from Eureka Server. The default value is true.
    # Single node doesn't matter. The cluster must be set to true to use load balancing with ribbon
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

# Exposure monitoring endpoint
management:
  endpoints:
    web:
      exposure:
        include: "*"

3.5 add message bus support to 3366 configuration center client

Modify pom add dependency

		<!-- Add message bus RabbitMQ support -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

Modify bootstrap yaml

server:
  port: 3366

spring:
  application:
    name: cloud-config-client
  cloud:
    # config client configuration
    config:
      label: master # Branch name
      name: config # Profile name
      profile: dev # Suffix
      uri: http://localhost:3344 # configuration center address
  # rabbitmq related configuration
  rabbitmq:
    host: 47.107.124.79
    port: 5672
    username: admin
    password: admin

eureka:
  instance:
    instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port} # Set instance access address
    prefer-ip-address: true # Set the access path to display the ip address
  client:
    # Indicates that you are registered with Eureka Server. The default value is true
    register-with-eureka: true
    # Whether to retrieve your existing registration information from Eureka Server. The default value is true.
    # Single node doesn't matter. The cluster must be set to true to use load balancing with ribbon
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

# Exposure monitoring endpoint
management:
  endpoints:
    web:
      exposure:
        include: "*"

3.6 testing

Modify the configuration file on GitHub
Send a post request to the configuration center server
curl -X POST "http://localhost:3344/actuator/bus-refresh"
One send takes effect everywhere

Configuration center
http://localhost:3344/config-dev.yaml

client
Get the configuration information and find that it has been refreshed

One amendment, broadcast notice, takes effect everywhere

4. Spring cloud bus dynamically refreshes fixed-point notifications

I don't want to be notified in full, but I just want to be notified at a fixed point

Specify that a specific instance takes effect instead of all
Formula: http:ip: configuration center port / Actor / bus refresh / {destination}
/The bus refresh request is no longer sent to the specific service instance, but to the config server. And specify the service or instance that needs to send updated configuration through the destination parameter class

Case:

  • We just want to refresh the cloud config client running on port 3355 as an example
    Only 3355, not 3366
  • curl -X POST "http://localhost:3344actuator/bus-refresh/cloud-config-clent:3355"

Notification summary

Topics: Java Spring