1.工作流程
配置中心就是将配置统一管理,这个配置可以统一到本地文件,也可以统一到Git仓库。
config-client从config-server获取了foo的属性,而config-server是从git仓库读取的,如图:
2.读取本地的配置文件
首先创建一个Model工程作为cinfig-server。这个工程就是一个简单的springboot项目,但是这里要注意,这个Model不能是之前那些项目(包括eureka、feign、ribbon、zuul、hystrix等)的子模块,因为之前导了很多jar包进去了,可能导致了未知jar包冲突。出现的现象就是config-server能正常启动,但是config-client拿不到配置文件的值,连启动端口都拿不到。自动注入的值也无法注入。所以重新新建一个Model,不让他作为之前工程的子模块。
新建的这个cinfig-server工程,pom文件:加入cinfig-server的依赖
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wx</groupId>
<artifactId>config-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-server</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
yml文件:
server:
port: 8769
spring:
cloud:
config:
server:
native:
search-locations: classpath:/shared
profiles:
active: native
application:
name: config-sever
spring. profiles.active:=native表示configserver是从本地读取配置,本地配置的位置在search-locations: classpath:/shared
配置的文件名字为 config-client-dev.yml。配置的内容为:这个端口作为config-client的启动端口。
server:
port: 8770
foo: foo verdion 1
最后一步是在启动类上加注解@EnableConfigServer 开启configserver的功能。
但是打包的时候报错:[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.21.0:test (default-t
解决办法:将打包命令写成:mvn install package -Dmaven.test.skip=true,或者在pom文件中加入:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
连接来源:https://www.cnblogs.com/lxcy/p/8279899.html
继续创建一个Model作为config-client,依然是一个独立的模块,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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wx</groupId>
<artifactId>config-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
此时的这个yml文件必须写成bootstrap.yml,因为bootstrap.yml比application.yml 优先执行。下面是bootstrap与application的简单区别:
bootstrap.yml 和application.yml 都可以用来配置参数
bootstrap.yml可以理解成系统级别的一些参数配置,这些参数一般是不会变动的
application.yml 可以用来定义应用级别的
bootstrap中配置一些系统参数,如果应用参数配置里面,很多不识别
bootstrap.yml内容:
spring:
application:
name: config-client
cloud:
config:
uri: http://localhost:8769/
fail-fast: true
profiles:
active: dev
这里指定了配置文件从哪里获取,还有获取的配置文件名字为spring.application.name-spring profiles.active。所以这里就是 config-client-dev.yml
打包启动,config-client的端口为config-server中配置文件
在client中加上:
@RestController
public class TestController {
@Value("${foo}")
String foo;
@RequestMapping(value = "/hi")
public String hi(){
return foo;
}
}
确实拿到了配置文件。
3.读取git上的配置文件
首先需要在git上准备这样一个配置文件:
如何上传一个文件到git可以参考:https://www.cnblogs.com/onephp/p/6116716.html
大致步骤如下:
Mkdir git01
Git init
Git add data.txt
Git commit -m “第一次提交”
Git remote add origin ...
Git push -u origin master
取消与本地仓库的关联:git remote remove origin
此时server的yml文件为:
server:
port: 8769
spring:
cloud:
config:
server:
git:
uri: https://github.com/WangAlainDelon/Test/
search-paths: conf
label: master
application:
name: config-sever
client的yml文件:
spring:
application:
name: conf
cloud:
config:
uri: http://localhost:8769/
fail-fast: true
profiles:
active: dev
server:
port: 8770
修改变量:
@RestController
public class TestController {
@Value("${java}")
String foo;
@RequestMapping(value = "/hi")
public String hi(){
return foo;
}
}
访问ok没有问题。
那么如何知道config-server是否读到了配置文件呢?
访问:http://localhost:8769/java/dev
这个配置文件的起名规则:
- application:应用名
- profile:环境
- label:版本
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
4.构建高可用的Config-Server
当服务实例很多时,都从配置中心读取文件,这时可以考虑将配置中心做成一个微服务,将其集群化,从而达到高可用,config-server和config-client向eureka-server注册,且将config-server多实例集群部署,架构图如下:
将config-server改造,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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wx</groupId>
<artifactId>config-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-server</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
yml文件改成:
server:
port: 8769
spring:
cloud:
config:
server:
git:
uri: https://github.com/WangAlainDelon/Test/
search-paths: conf
label: master
application:
name: config-server
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/
这个感觉就像是一个服务提供者,他的服务名字为config-server,然后给出注册中心的地址让他去注册。
最后需要在启动类上加上注解,开启Eureka的功能。
其次改造config-client,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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wx</groupId>
<artifactId>config-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
bootstrap.yml文件:
spring:
application:
name: conf
cloud:
config:
fail-fast: true
discovery:
enabled: true
service-id: config-server
profiles:
active: dev
server:
port: 8770
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/
这个service-id就是配置服务的名字。加上注解开启Eureka的功能。
启动eureka-server,config-server,config-client:
启动多个config-server的实例,config-client会轮询的方式去访问每个config-server实例,即做了负载均衡。
5.Spring Cloud Bus来刷新配置
Spring Cloud Bus 将分布式的节点用轻量的消息代理连接起来。它可以用于广播配置文件的更改或者服务之间的通讯,也可以用于监控。本文要讲述的是用Spring Cloud Bus实现通知微服务架构的配置文件的更改。消息总线是一种通信工具,可以在机器之间互相传输消息、文件等。消息总线扮演着一种消息路由的角色,拥有一套完备的路由机制来决定消息传输方向。发送段只需要向消息总线发出消息而不用管消息被如何转发。Spring cloud bus 通过轻量消息代理连接各个分布的节点。管理和传播所有分布式项目中的消息,本质是利用了MQ的广播机制在分布式的系统中传播消息,目前常用的有Kafka和RabbitMQ。
总结就一句话:当git上的配置文件修改了以后,只需要向集群中的一个节点发送请求,他就会通知到消息总线,消息总线就会通知整个集群重新拉取配置文件。
首先安装消息队列RabbitMQ:参考链接:https://blog.csdn.net/newbie_907486852/article/details/79788471
1.下载安装erlang,一直下一步就行。
配置环境变量:
- 安装完成之后创建一个名为ERLANG_HOME的环境变量,其值指向erlang的安装目录。
- 同将%ERLANG_HOME%\bin加入到Path中
erlang安装成功
2.安装rabbitMQ:
激活 RabbitMQ’s Management Plugin
点击启动:
默认的登陆账号为:guest,密码为:guest。
目前Spring Cloud Bus 支持 RabbitMQ 和 Kafka,AMQP等等。
改造client工程,在pom文件加上起步依赖spring-cloud-starter-bus-amqp(消息总线依赖)spring-boot-starter-actuator(模块是一个spring提供的监控模块)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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wx</groupId>
<artifactId>config-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
<!--spring监控依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<!--消息总线依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-bus-amqp -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
bootstrapyml文件,
spring:
application:
name: conf
cloud:
config:
fail-fast: true
discovery:
enabled: true
service-id: config-server
bus:
enabled: true
trace:
enabled: true
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
profiles:
active: dev
server:
port: 8772
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/
management:
endpoints:
web:
exposure:
include: bus-refresh
加上注解@RefreshScope,才会在不重启服务的情况下更新配置。
因为bootstarp.yml做多环境配置文件后,config-client无法读取,所以在IDEA中启动多个config-client实例,去掉勾,修改端口就可以启动多个实例:
下面启动eureka-server,config-server,三个config-client
这时我们去代码仓库将java的值改为“javaEE123”,即改变配置文件JAVA的值。如果是传统的做法,需要重启服务,才能达到配置文件的更新。此时,我们只需要发送post请求:http://localhost:8770/actuator/bus-refresh,你会发现config-client会重新读取配置文件。
MQ:
post请求为:http://localhost:8770/actuator/bus-refresh?destination=eureka-client:**
即指定刷新所有名字为eureka-client的服务实例。
参考链接:https://blog.csdn.net/seapeak007/article/details/77527533