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