11. Chapter 11 of spring cloud, upgrading, service GateWay gateway, service configuration Config and service Bus bus

Keywords: Programming Spring git Maven RabbitMQ

Chapter 10 of spring cloud, upgrading, service GateWay gateway, service configuration Config and service Bus bus

1, Service GateWay

1. Gateway overview

Why does it exist:

Different microservices usually have different network addresses, and external clients may need to call multiple microservices interfaces to fulfill the requirements of a business
Direct communication between the client and multiple microservices will cause many problems:

a. Clients request different microservices many times, increasing the complexity of clients
b. There are cross domain requests, which are difficult to handle in certain scenarios
c. Authentication is complex, and each microservice needs independent authentication
d. It's difficult to refactor, and as the project iterates, you may need to re divide the microservices.
	For example, multiple microservices may be merged into one or one microservice may be split into multiple microservices. This is to increase the difficulty of reconfiguration if the client directly communicates with each microservice.
e. Some microservices may use the unfriendly protocol of firewall or browser, so it will be difficult to access them directly.

What is a service gateway:

Gateway is the middle layer between client and server. All external requests go through the gateway layer. That is to say, more consideration should be given to business logic in API implementation. The security, performance and monitoring can be done by the friendship gateway. This improves the flexibility and security of the business.

What are the advantages:

a. Security, only the gateway system is exposed to the outside, the micro service can be hidden in the intranet, protected by the firewall.
b. It is easy to monitor and can collect monitoring data in gateway and push it to external system for monitoring.
c, Easy and authentication, can be authenticated on the gateway, and then forward the request to the back-end micro service, without authentication on each micro service.
d. It reduces the number of interactions between clients and microservices.
e. Easy to unify authentication. Verify that the user has access to the microservices.

2. What is GateWay

What is it?

Bottom line: gateway is an alternative to zuul 1. X.

Spring cloud gateway aims to provide a simple and effective unified API route management method for microservice architecture. The basic functions of the gateway are provided based on the filter chain: security, monitoring, fusing, current limiting, Retry, etc.

What can I do

Reverse agent, authentication, flow control, fusing, log monitoring, etc

The difference between gateway and zuul1.x:

zuul1.x is a blocking processing model based on servlet s.
gateway is non blocking.

3. Core concepts

a. Assert predicate:
	With reference to java8's predicate, developers can match everything in the http request. Route if the request matches the route.

b. Filter:
	It refers to the instance of spring gateway in the spring framework, which can modify the request before or after routing.

c. Route:
	Routing is the basic module of building gateway, which consists of ID, target URI, a series of predicate and filter. Match the route if the assertion is true.


Through some matching conditions, the web request is located to the real service node, and a series of fine control is carried out before and after the forwarding process.

predicate is our matching condition, and filter can be understood as an omnipotent interceptor. With these two elements and a uri, a specific route can be realized.

4. gateway workflow

The client sends a request to the spring cloud gateway, finds the route matching the request in the gateway handler mapping, and sends it to the gateway web handler

The handler then sends the request through the specified filter chain to the actual service to execute the business logic, and then returns.

The filter may pre or post the business logic before or after sending the request.

pre: parameter verification, permission verification, traffic monitoring, log output, protocol conversion, etc.
post: modification of corresponding content and response header, log output, traffic monitoring, etc.

5. Cases

5.1 add 9527 gateway in front of the producer

New module: cloud-gateway-9527

<parent>
    <artifactId>cloud_2020</artifactId>
    <groupId>com.lee.springcloud</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-gateway-9527</artifactId>

POM:

<?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>cloud_2020</artifactId>
        <groupId>com.lee.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-gateway-9527</artifactId>


    <dependencies>
        <!--Newly added gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.lee.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

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

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>



    </dependencies>


</project>

application.yml

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #ID of the route. There is no fixed rule but it is unique. It is recommended to cooperate with the service name
          uri: http://localhost:8001 - the routing address of the service after matching
          predicates:
            - Path=/payment/get/**   #Assert, route with matching path

        - id: payment_routh2
          uri: http://localhost:8001
          predicates:
            - Path=/payment/lb/**   #Assert, route with matching path


eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

Main startup class:

@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {

    public static void main(String[] args) {
        SpringApplication.run(GateWayMain9527.class,args);
    }
    
}

Test:

1. Launch eureka7001, provider-8001, gateway-9527
2. Visit: http://localhost:8001/payment/get/1
3. Visit: http://localhost:9527/payment/get/1

The results are:
{"code":200,"message": "query data successfully serverPort:8001Payment(id=1, serial=001)","data":null}

Implemented a 9527 before the 8001 service.

5.2 optimization

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #ID of the route. There is no fixed rule but it is unique. It is recommended to cooperate with the service name
          uri: http://localhost:8001 - the routing address of the service after matching
          predicates:
            - Path=/payment/get/**   #Assert, route with matching path

        - id: payment_routh2
          uri: http://localhost:8001
          predicates:
            - Path=/payment/lb/**   #Assert, route with matching path

At present, our configuration is based on the specific address of the microservice. However, the payment provider's microservices may have multiple services in the actual production environment. So we need to dynamically route based on the provider's microservice name in the registry.

By default: gateway creates a dynamic route based on the service list of the registry and the name of the microservice on the registry for forwarding, so as to realize the function of dynamic route.

Modify cloud-gateway-9527 application.yml

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #ID of the route. There is no fixed rule but it is unique. It is recommended to cooperate with the service name
          ##uri: http://localhost:8001 - the routing address of the service after matching
          uri: lb://Cloud payment service ා LB indicates that the gateway enabled load balancing function finds the URI in eureka according to the microservice name
          predicates:
            - Path=/payment/get/**   #Assert, route with matching path

        - id: payment_routh2
          ##uri: http://localhost:8001
          uri: lb://Cloud payment service ා LB means to enable the load balancing function of gateway to find the URI in eureka according to the microservice name
          predicates:
            - Path=/payment/lb/**   #Assert, route with matching path


eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

Test:

1. Start eureka-7001, provider-8001, provider-8002, gateway-9527
2. Visit: http://localhost:9527/payment/get/1

Result return:
{"code":200,"message": "query data successfully serverPort:8001Payment(id=1, serial=001)","data":null}
perhaps
{"code":200,"message": "query data successfully serverPort:8002Payment(id=1, serial=001)","data":null}


The use of 8001 and 8002 port microservice polling proves that we can call the corresponding microservice by visiting 9527 through the microservice name

5.3 use of Predicate

When we start cloud-gateway-9527, the background is loaded as follows:

Spring cloud gateway has many route predicate factories built in, which match different properties of http requests. Multiple
route predicate can be used in combination.

Spring cloud gateway creates a route object, routepredictefactory creates a predict object, and the predict object is assigned to route.

Common route predicate:

1,After Route Predicate
	//Example: - After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]


2,Before Route Predicate
	//Example: - After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]


3,Between Route Predicate
	//For example: - between = 2020-03-08t10:59:34.102 + 08:00 [Asia / Shanghai], 2020-03-08t10:59:34.102 + 08:00 [Asia / Shanghai]

4,Cookie Route Predicate
	//For example: - Cookie=username,lee and cookie is username=lee to access

5,Header Route Predicate
	//For example: - header = X-Request-Id, D + ා regular expression with X-Request-Id attribute and integer value in request header

6,Host Route Predicate
	//Example: - Host=**.ngc7293.com

7,Method Route Predicate
	//Example: - Method=GET

8,Path Route Predicate
	//Example: - Path=/payment/get / * * ා assert, route the path matching

9,Query Route Predicate
	//Example: - Query=username, \d + ා parameter name and positive integer are required to route

//Summary:
 - id: payment_routh2
    #uri: http://localhost:8001 - the routing address of the service after matching
    uri: lb://cloud-payment-service
    predicates:
        - Path=/payment/lb/**   #Assert, route with matching path
        - After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
        - Cookie=username,lee #And the Cookie can only be accessed if it is username=lee
        - Header=X-Request-Id, \d+ #Regular expression with X-Request-Id attribute and integer value in request header
        - Host=**.ngc7293.com
        - Method=GET
        - Query=username, \d+ #Must have parameter name and be a positive integer to route


To put it bluntly, predict is to implement a set of matching rules and let the request come to find the corresponding Route for processing

5.4 use of Filter

The gateway often needs to Filter the routing requests and perform some operations, such as constructing the header after authentication. There are many kinds of filtering, such as adding the request header, adding the request parameters, adding the response header and the circuit breaker and so on. This uses the Spring Cloud Gateway Filter.

When we have many services, such as user service, goods service, sales service, etc. in the figure below, when the client requests the Api of each service, each service needs to do the same thing, such as authentication, current restriction, log output, etc.

For such repeated work, you can add a global Api Gateway service of permission control, current restriction and log output on the upper layer of the microservice, and then forward the request to the specific business service layer. The Api Gateway service serves as a service boundary. External requests to access the system must first pass through the gateway layer.

Spring Cloud Gateway's Filter life cycle is not as rich as Zuul's, it only has two: "pre" and "post".

PRE: this filter is called before the request is routed. We can use this filter to implement authentication, select requested microservices in the cluster, record debugging information, etc.

POST: this filter is executed after routing to the microservice. This filter can be used to add standard HTTP headers for responses, collect statistics and metrics, send responses from microservices to clients, and so on.

Spring Cloud Gateway Filter can be divided into two other types of GatewayFilter and GlobalFilter from the scope of action.

GatewayFilter: applied to a single route or a group of routes.

GlobalFilter: applied to all routes.

5.4.1,GatewayFilter

Use Demo:

The filter factory will add a pair of request headers with the name of X-Request-Foo and the value of Bar to the matching request headers.

All / foo / * * start paths will hit the configured router. Request http://www.abc.com/foo/get, go to http://www.abc.com.org/get]

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: http://httpbin.org:80/get
        filters:
        - AddRequestHeader=X-Request-Foo, Bar
		- RewritePath=/foo/(?<segment>.*), /$\{segment}
        predicates:
        - Method=GET

Custom Gateway Filter:

@Component
@Slf4j
public class MyLogGatewayFilter implements GatewayFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("-----welcome to MyLogGatewatFilter------"+new Date());
        String username = exchange.getRequest().getQueryParams().getFirst("username");
        if(StringUtils.isEmpty(username)){
            log.info("username is empty!!!");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

config:

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder myLogGatewayFilterBuilder = routeLocatorBuilder.routes().route("myLogGatewayFilter",
                r -> r.path("/payment/get/**")
                        .uri("lb://cloud-payment-service")
                        .filter(new MyLogGatewayFilter()));

        return myLogGatewayFilterBuilder.build();
    }
}

Test:

1. Launch eureka-7001, payment-provider-8001, payment-provider-8002, gateway-9527
2. Visit: http://localhost:9527/payment/get/1
	Result: failed
3. Visit: http://localhost:9527/payment/get/1?username=lee
	result:
	{"code":200,"message": "query data successfully serverPort:8001Payment(id=1, serial=001)","data":null}

5.4.2,GlobalFilter

Customize globalFilter

@Component
@Slf4j
public class MyGlobalGatewayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("-----welcome to MyGlobalGatewatFilter------"+new Date());
        String password = exchange.getRequest().getQueryParams().getFirst("password");
        if(StringUtils.isEmpty(password)){
            log.info("password is empty!!!");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

Test:

1. Launch eureka-7001, payment-provider-8001, payment-provider-8002, gateway-9527
2. Visit: http://localhost:9527/payment/get/1
	Result: failed
3. Visit: http://localhost:9527/payment/get/1?username=lee
	Result: failed
4. Visit: http: / / localhost: 9527 / payment / get / 1? Username = Lee & password = admin123
	result:
	{"code":200,"message": "query data successfully serverPort:8001Payment(id=1, serial=001)","data":null}

2, Distributed configuration center Config

1. Config overview

Spring cloud config provides centralized external configuration support. The configuration server provides a centralized external configuration for all environments of different microservice applications.

Spring cloud config is a set of centralized and dynamic configuration management services

Spring cloud config is divided into two parts: server and client.

The server also becomes a distributed configuration center. It is an independent microservice application, which is used to connect the configuration server and provide the client with access interfaces to obtain configuration information, encrypt and decrypt information.

The client manages application resources and business related configuration content through the specified configuration center, and obtains and loads configuration information from the configuration center at startup.

The configuration server uses Git to store configuration information by default, which is helpful for version management of environment configuration and can access and manage configuration content through Git client tools.


What to do:

1. Centralized management profile
2. Different configurations in different environments, dynamic configuration updates, deployment of dev test prod beta release in different environments
3. Dynamically adjust configuration during operation
4. When the configuration changes, the service does not need to restart to be aware
5. Expose configuration information as a rest interface

2. Cases

2.1. Server config server

2.1.1 new warehouse

①,New on code cloud springcloud-config2020 Warehouse
②,Get SSH Agreed Git address
③,New on local hard disk directory Git Warehouse and clone
	git clone xxxxxxxxxxxxxxxxxxxxxxxxxxx.git
④,Create a new one application.yml(The format of file content saving must be UTF-8)
⑤,Upward yml File push to gitee upper
	git status #View status
	git add . 
	git commit -m "init file"
	git push origin master

application.yml [to be the configuration file of config client side]

spring:
  application:
    name: cloud-payment-service #Own service name
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/cloud2020?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: admin123

eureka:
  client:
    register-with-eureka: true #Register yourself with eureka server
    fetch-registry: true #You need to go to the registration center to get the address of other services
    service-url:
      #defaultZone: http://localhost:7001/eureka ා stand alone point to Eureka service registry
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002:7002.com/eureka ා cluster execution Eureka service registry
  instance:
    instance-id: cloud-provider-payment-service-8007
    prefer-ip-address: true #Show service IP address or not

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.lee.springcloud.entities
  ##configuration:
    ##log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #Console print SQL

2.1.2 new configuration center

New module module cloud-config-3344 configuration center module

<parent>
    <artifactId>cloud_2020</artifactId>
    <groupId>com.lee.springcloud</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-config-3344</artifactId>

POM

<?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>cloud_2020</artifactId>
        <groupId>com.lee.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-3344</artifactId>

    <dependencies>

		<!--config server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        
        
        
        <dependency>
            <groupId>com.lee.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </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>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

application.yml

server:
  port: 3344
spring:
  application:
    name: cloud-config
  cloud:
    config:
      server:
        git:
          uri:  https://Gitee.com/night-wish/springcloud-config2020.git-name of the corresponding warehouse on gitee
          username: sssssssss@qq.com  #Gitee's corresponding account and password
          password: ssssssssssssss
          search-paths:
            - sprincloud-config2020  #Corresponding warehouse name
      label: master #Corresponding branch
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

Main startup class:

@SpringBootApplication
@EnableConfigServer
public class ConfigMain3344 {

    public static void main(String[] args) {
        SpringApplication.run(ConfigMain3344.class,args);
    }

}

2.1.3 other configurations

modify HOST
127.0.0.1 config3344.com
①①,start-up config Test whether the gitee Get configuration content on
	http://config3344.com:3344/application-dev.yml
	http://config3344.com:3344/application-test.yml
	http://config3344.com:3344/application-xxxxx.yml
    //or
	http://config3344.com:3344/application/dev/master
	http://config3344.com:3344/application/test/master
	http://config3344.com:3344/application/xxxxx/master

2.2. Client config client

Client as a microservice, create cloud-provider-payment-8007 following cloud-provider-payment-8001

POM

<?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>cloud_2020</artifactId>
        <groupId>com.lee.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>cloud-provider-payment-8007</artifactId>


    <dependencies>
        
        <!-- SpringCloud Config client -->
        <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>

        <!--springboot-->
        <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>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

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

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

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--cloud-api-commons Public package-->
        <dependency>
            <groupId>com.lee.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

    </dependencies>

</project>

application.yml

server:
  port: 8007

bootstrap.yml

spring:
  cloud:
    config:
      name: application #The resource name that needs to be read from gitee, note that there is no yml suffix
      profile: dev   #Configuration items accessed this time
      label: master   
      uri: http://config3344.com:3344 ා after starting the microservice, go to the 3344 service first, and get the service address of Gitee through SpringCloudConfig

Create ConfigClientRestController class

@RestController
public class ConfigClientRestController {

    @Value("${spring.application.name}")
    private String applicationName;

    @Value("${eureka.client.service-url.defaultZone}")
    private String eurekaServers;

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

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

    @RequestMapping("/config")
    public String getConfig()
    {
        String str = "applicationName: "+applicationName+"\t eurekaServers:"+eurekaServers+"\t port: "+port;
        System.out.println("******str: "+ str);
        return "applicationName: "+applicationName+"\t eurekaServers:"+eurekaServers+"\t port: "+port;
    }

    @RequestMapping("/info")
    public String getName(){
        return "config.info : "+info;
    }


}

Main startup class:

//Service discovery
@EnableDiscoveryClient
//Indicates that it is the client of Eureka
@EnableEurekaClient
@SpringBootApplication
@MapperScan("com.lee.springcloud.dao")
public class PaymentMain8007 {

    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8007.class,args);
    }
}

The rest of the controller s, service s, Daos and mapper s are created after the cloud-payment-provider-8001

Test:

1. Start eureka-7001, config-3344, cloud provider-payment-8007
2. Visit http://localhost:8007/info
	result:
	config.info : hello-world
	Prove that you can access the application.yml configuration information on the code cloud through config-3344 and read its content
3. Visit http://localhost:8007/payment/get/1
	result:
	{"code":200,"message": "query data successfully serverPort:8007Payment(id=1, serial=001)","data":null}
	Prove that the application.yml configuration information on the code cloud can be accessed through config-3344

2.3. The client only needs to refresh dynamically

In the code cloud sprincloud-config2020 Modify application.yml on

config:
   info: hello-world2 #It turns out to be Hello world

visit: http://localhost:3344/application-dev.yml

result:
config:
  info: hello-world2
. . . .  Other omissions

visit: http://localhost:8007/info

result:
config.info : hello-world

Restart cloud-provider-payment-8007, visit http://localhost:8007/info

result:
config.info : hello-world2

Solution:

cloud-provider-payment-8007 introduced into actor monitoring

pom

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

application.yml

management:
  endpoints:
    web:
      exposure:
        include: "*"

controller NEW

@RefreshScope

Operation and maintenance personnel manually send POST request to refresh 8007

curl  -X POST "http://localhost:8007/actuator/refresh"

Test:

1. Modify code cloud
config:
  info: hello-world3
2. Visit http://localhost:3344/application-dev.yml
result:
config:
  info: hello-world2
. . . .  Other omissions

3. Visit http://localhost:8007/info
result:
config.info : hello-world3

3, Message Bus

For the above config client, if there are multiple cloud provider payment 800xxx, the operation and maintenance personnel need to manually POST the request every time they modify the configuration file, which is very troublesome. So whether it can be broadcast, a notice will take effect everywhere and refresh in a wide range. This leads to the message BUS.

1. Overview

Spring cloud bus is a framework to link nodes of distributed system with lightweight message system.

It integrates java event processing mechanism and message middleware functions

Spring cloud bus currently only supports RabbitMq and Kafka

Spring cloud bus can manage and propagate messages between distributed systems, just like a distributed actuator, which can be used to broadcast state changes, time push, etc.
It can also be used as a communication channel between microservices.

What is a bus
In a microservice architecture system, a lightweight message broker is usually used to build a common message subject and connect all microservice instances in the system. Because messages generated in this topic will be listened and consumed by all instances, it is called message bus. Each instance on the bus can easily broadcast messages that need to be known by other instances linked in the subject line.
 
Basic principle:
ConfigClient instances listen to the same topic in MQ (spring cloudbus 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. Installing RabbotMq

① . install Erlang environment
	http://erlang.org/download/otp_win64_21.3.exe
② . install Rabbit
	https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.14/rabbitmq-server-3.7.14.exe
③ , start management add visual plug-in
cd F:\JavaTools\RabbitMq\rabbitmq_server-3.7.14\sbin
Execute rabbitmq-plugins enable rabbitmq management
④ , start rabbitmq and visit http://localhost:15672/
Account: guest password: Guest

3. Create another config client

Then create a config client with cloud-provider-payment-8007

cloud-provider-payment-8008

<parent>
    <artifactId>cloud_2020</artifactId>
    <groupId>com.lee.springcloud</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cloud-provider-payment-8008</artifactId>

application.yml

server:
  port: 8008

Main startup class

//Service discovery
@EnableDiscoveryClient
//Indicates that it is the client of Eureka
@EnableEurekaClient
@SpringBootApplication
@MapperScan("com.lee.springcloud.dao")
public class PaymentMain8008 {

    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8008.class,args);
    }
}

4. Design ideas

4.1 use message bus to trigger a client / bus/refresh and refresh the configuration of all clients

4.2 use message bus to trigger / bus/refresh endpoint of ConfigServer, and refresh configuration of all clients (more recommended)

5. Dynamic refresh of global broadcast cases

5.1. Add message bus support to config server

cloud-config-3344

POM NEW

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

yml NEW

server:
  port: 3344
spring:
  application:
    name: cloud-config
  cloud:
    config:
      server:
        git:
          uri:  https://Gitee.com/night-wish/springcloud-config2020.git-name of the corresponding warehouse on gitee
          username: ooooooooo
          password: xxxxxxxxx
          search-paths:
            - sprincloud-config2020
      label: master
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

#New bus
rabbitmq:
  host: localhost
  port: 5672
  username: guest
  password: guest
#New bus
management:
  endpoints:
    web:
      exposure:
        include: 'bus-refresh'

controller NEW

@RefreshScope//Newly added
@RestController
public class ConfigClientRestController {
    //. . . .  ellipsis
}

5.2. Add message bus support to config client

cloud-provider-payment-8007 and cloud-provider-payment-8008

POM NEW

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

bootstrap.yml

spring:
  cloud:
    config:
      name: application #The resource name that needs to be read from gitee, note that there is no yml suffix
      profile: dev   #Configuration items accessed this time
      label: master
      uri: http://config3344.com:3344 ා after starting the microservice, go to the 3344 service first, and get the service address of Gitee through SpringCloudConfig

#Newly added
rabbitmq:
  host: localhost
  port: 5672
  username: guest
  password: guest

#Newly added
management:
  endpoints:
    web:
      exposure:
        include: "*"

5.3 test

1. Start eureka-7001 config-3344 cloud-provider-payment-8007 cloud-provider-payment-8008
2. Visit:
http://localhost:3344/application-dev.yml
http://localhost:8007/info
http://localhost:8008/info

result:
config:
  info: hello-world3
and
config.info : hello-world3
and
config.info : hello-world3

3. Modify the value hello-world3 in application.yml in springcloud-config2020 to hello-world4
4. Visit above again

result:
config:
  info: hello-world4
and
config.info : hello-world3
and
config.info : hello-world3

5. Operation and maintenance personnel send refresh to config server

curl -X POST "http://localhost:3344/actuator/bus-refresh"

6. Visit above again

result:
config:
  info: hello-world4
and
config.info : hello-world4
and
config.info : hello-world4


Summary:
  We use message bus to trigger a / bus/refresh endpoint of ConfigServer (config-3344), and refresh the configuration of all clients

6. Dynamically refresh fixed-point notification cases

Sometimes we need to refresh only one or several config clients rather than all config clients after data update, so it's important to dynamically refresh fixed-point notifications.

Formula:

http://localhost: port number of configuration center / Actor / bus refresh / {destination}

Case test:

1. Start eureka-7001 config-3344 cloud-provider-payment-8007 cloud-provider-payment-8008
2. Visit:
http://localhost:3344/application-dev.yml
http://localhost:8007/info
http://localhost:8008/info

result:
config:
  info: hello-world4
and
config.info : hello-world4
and
config.info : hello-world4

3. Modify the value hello-world4 in application.yml in springcloud-config2020 to hello-world5
4. Visit above again

result:
config:
  info: hello-world5
and
config.info : hello-world4
and
config.info : hello-world4

5. Operation and maintenance personnel send refresh to config server

curl -X POST "http://localhost:3344/actuator/bus-refresh/cloud-payment-service:8007"

6. Visit above again

result:
config:
  info: hello-world5
and
config.info : hello-world5
and
config.info : hello-world4

Posted by AutomatikStudio on Thu, 23 Apr 2020 20:51:35 -0700