diff --git a/pictures/api gateway.png b/pictures/apiGateway.png similarity index 100% rename from pictures/api gateway.png rename to pictures/apiGateway.png diff --git a/pictures/config-a.png b/pictures/config-a.png new file mode 100644 index 0000000..1196fb6 Binary files /dev/null and b/pictures/config-a.png differ diff --git a/pictures/config-application-dev.png b/pictures/config-application-dev.png new file mode 100644 index 0000000..5f3b238 Binary files /dev/null and b/pictures/config-application-dev.png differ diff --git a/pictures/config-client-programmer.png b/pictures/config-client-programmer.png new file mode 100644 index 0000000..e404329 Binary files /dev/null and b/pictures/config-client-programmer.png differ diff --git a/pictures/config-dev.png b/pictures/config-dev.png new file mode 100644 index 0000000..a1c3c70 Binary files /dev/null and b/pictures/config-dev.png differ diff --git a/pictures/config-git.png b/pictures/config-git.png new file mode 100644 index 0000000..c906fb8 Binary files /dev/null and b/pictures/config-git.png differ diff --git a/pictures/spring-cloud-bus-exchange.png b/pictures/spring-cloud-bus-exchange.png index e8b5ea8..53d0959 100644 Binary files a/pictures/spring-cloud-bus-exchange.png and b/pictures/spring-cloud-bus-exchange.png differ diff --git a/pictures/spring-cloud-bus-queue.png b/pictures/spring-cloud-bus-queue.png index cc075ff..c8b95b0 100644 Binary files a/pictures/spring-cloud-bus-queue.png and b/pictures/spring-cloud-bus-queue.png differ diff --git a/pictures/spring-cloud-config.png b/pictures/spring-cloud-config.png new file mode 100644 index 0000000..07a534c Binary files /dev/null and b/pictures/spring-cloud-config.png differ diff --git a/spring-cloud/spring-cloud-config/README.md b/spring-cloud/spring-cloud-config/README.md index b2e6b1e..2c66b37 100644 --- a/spring-cloud/spring-cloud-config/README.md +++ b/spring-cloud/spring-cloud-config/README.md @@ -1,32 +1,433 @@ -配置中心拉取git配置文件: -```$xslt -[on(6)-127.0.0.1] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/D:/git-config/spring-cloud/spring-cloud-test-config/application.yml -[nio-8010-exec-2] pClientConfigurableHttpConnectionFactoryx : No custom http config found for URL: https://github.com/heibaiying/spring-samples-for-all/info/refs?service=git-upload-pack -[nio-8010-exec-2] o.s.cloud.commons.util.InetUtils : Cannot determine local hostname -[nio-8010-exec-2] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/D:/git-config/spring-cloud/spring-cloud-test-config/application-dev.yml -[nio-8010-exec-2] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/D:/git-config/spring-cloud/spring-cloud-test-config/application.yml +# spring-cloud-config + +## 一、config 简介 + +spring cloud config 分为服务端和客户端,服务端称为分布式配置中心,集中管理配置文件,客户端为各个业务单元,它们从配置中心获取相关配置,同时config 还实现了配置热更新,在服务不停机的情况下刷新配置。 + + + +## 二、项目结构 + ++ config-server: 配置中心; ++ config-client: 服务单元,可以从配置中心获取相关配置; ++ eureka: 注册中心。 + +
+ + + + + +## 三、config-server 配置中心的实现 + +#### 3.1 导入依赖 + +```xml + + + 4.0.0 + + + com.heibaiying.config + spring-cloud-config + 0.0.1-SNAPSHOT + + + config-server + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-config-server + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + ``` -每次启动时候都会去注册中心拉取最新的代码,但是已经启动的项目是不会热更新的 -```$xslt -2019-01-17 13:35:14.986 INFO 4448 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8020/ -2019-01-17 13:35:20.910 INFO 4448 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=config-client, profiles=[dev], label=master, version=50dcfb85cd751e4f28761cd6bad84c1f73034002, state=null + + +#### 3.2 在启动类上添加@EnableDiscoveryClient和@EnableConfigServer 注解 + +```java +@SpringBootApplication +@EnableDiscoveryClient +@EnableConfigServer +public class ConfigServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ConfigServerApplication.class, args); + } + +} ``` -消息总线 -```$xslt -2019-01-17 13:37:50.998 INFO 4448 --- [e0bL-TWAMhWg-19] o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory#496c6d94:22/SimpleConnection@185d85d2 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 63713] -2019-01-17 13:37:51.015 INFO 4448 --- [e0bL-TWAMhWg-19] o.s.amqp.rabbit.core.RabbitAdmin : Auto-declaring a non-durable, auto-delete, or exclusive Queue (springCloudBus.anonymous.iY4TIIi9TSe0bL-TWAMhWg) durable:false, auto-delete:true, exclusive:true. It will be redeclared if the broker stops and is restarted while the connection factory is alive, but all messages will be lost. + + +#### 3.3 指定注册中心地址,并配置git仓库地址的配置文件路径 + +```yaml +server: + port: 8020 +# 指定注册中心地址 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:8010/eureka/ +# 指定服务命名 +spring: + application: + name: config-server + cloud: + config: + server: + git: + uri: https://github.com/heibaiying/spring-samples-for-all/ + search-paths: spring-cloud/spring-cloud-test-config/ + # 如果代码仓库是公开的 则 不需要设置用户名和密码 + username: + password: + # 指定拉取的配置文件的存放位置,配置文件最后存储的目录为 basedir + search-paths + # 这个地方还需要注意的是,配置文件的仓库最好只放配置文件 + # 因为配置中心不仅会拉取search-paths下的文件,还会把uri指定仓库中的全部文件拉取到basedir下 + basedir: D:\git-config + # 指定分支 + label: master ``` -刷新应用上下文,热更新 +这里的git 仓库就是本用例的仓库,是公开的仓库,所以不用配置用户名和密码,配置文件如下 -```$xslt +- application.yml 为主配置; +- application-dev.yml 为开发环境配置。 + +
+ + + +#### 3.4 启动eureka和config-server服务,访问 http://localhost:8020/application-dev.yml + +
+ +这里需要注意的拉取配置的时候,我们此时指定拉取的是dev配置,application.yml实际 配置如下: + +
+ +**这说明在用配置中心拉取配置的时候,和我们在本地开发的时候是一致的,配置是互补的,即dev中的实际配置应该是主配置和dev配置的结合,且遵循同名属性精确优先的原则**。 + + + +#### 3.5 http请求地址和资源文件映射 + +在本用例中如果我们想要直接访问主配置,用以下路径 http://localhost:8020/application.yml是不行的,会得到错误页面。如果想要访问主配置,,可以用http://localhost:8020/application-X.yml,其中可以是任意字符,原因是: + +请求地址和实际的配置文件应该遵循以下规则,application为配置文件名,profile 为环境,label为分支(如果不指定默认就是master分支)。 + +- /{application}/{profile}[/{label}] +- /{application}-{profile}.yml +- /{label}/{application}-{profile}.yml +- /{application}-{profile}.properties +- /{label}/{application}-{profile}.properties + +访问主配置: + +
+ + + +## 四、config-client 搭建 + +#### 4.1 导入依赖 + +```xml + + + 4.0.0 + + + com.heibaiying.config + spring-cloud-config + 0.0.1-SNAPSHOT + + + config-client + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-starter-config + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + +``` + +#### 4.2 新建 `bootstrap.yml`配置文件,指定注册中心地址和配置中心服务名,并在启动类上开启自动注册@EnableDiscoveryClient + +这里需要特别说明的是,在之前的所有项目中我们采用的配置文件都是application.yml,但是这里**一定要采用bootstrap.yml**。 + +假设我们的数据库配置是放在远程配置中心的,那么我们应该先去远程配置中心拉取配置,然后再去进行数据库的自动化配置,反之如果我们先进行了数据库的自动化配置,那么就会因为找不到url或驱动而抛出异常。 + +- bootstrap.yml(bootstrap.properties)用来程序引导时执行,应用于更加早期配置信息读取,bootstrap.yml 先于 application.yml 加载。 + +- application.yml(application.properties) 应用程序各个模块的配置信息。 + +```yaml +server: + port: 8030 +spring: + application: + name: config-client + cloud: + config: + discovery: + enabled: true + # 这里我们指定的是服务名 如果配置中心有多个,且用同一个服务名,我们的客户端拉取配置的时候是负载均衡的,配置中心也就是高可用的 + serviceId: config-server + # 指定分支 + label: master + # 指定环境 + profile: dev + + +# 注意指定注册中心的配置不要从公共配置中拉取,要在本地的配置文件中指定 +# 因为我们必须要先从注册中心去获取可用的配置中心, 从配置中心去拉取配置 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:8010/eureka/ + +``` + +```java +@SpringBootApplication +@EnableDiscoveryClient +public class ConfigClientApplication { + + public static void main(String[] args) { + SpringApplication.run(ConfigClientApplication.class, args); + } + +} + +``` + +#### 4.3 创建配置映射类用于测试 + +```java +@Component +@ConfigurationProperties(prefix = "programmer") +@Data +@ToString +public class Programmer{ + + private String name; + private int age; + private boolean married; + private Date hireDate; + private float salary; + private int random; + private Map skill; + private List company; + private School school; + +} +``` + +```java +@RestController +public class ConfigController { + + @Autowired + private Programmer programmer; + + @RequestMapping("programmer") + public String getProgrammer() { + return programmer.toString(); + } +} +``` + +#### 4.4 依次启动eureka,config-server,config-client ,访问 http://localhost:8030/programmer + +这里需要注意是在启动eureka和config-server,要稍等一会在启动config-client,这里是为了确保config-server已经将服务注册到eureka,然后我们的config-client才能从eureka中获取配置中心的服务。 + +
+ +启动的时候可以从控制台看到如下拉取服务的信息: + +```shell +Fetching config from server at : http://localhost:8020/ +Located environment: name=config-client, profiles=[dev], label=master, version=50dcfb85cd751e4f28761cd6bad84c1f73034002, state=null +``` + + + +## 五、集成 spring-cloud-bus 实现配置热更新 + +#### 5.1 消息总线简介 + +在微服务的架构中,我们通常想要构建一个共同的消息主题被所有微服务实例所监听,以便对所有微服务实例的管理和通知,这就是消息总线,spring cloud bus 就是消息总线的一种实现。 + +目前spring cloud bus 支持的消息中间件有 RabbitMQ和kafka, 我们下面的整合采用的是RrabbitMQ。 + +关于热更新只需要对配置客户端(config-client)做更改,不需要对(config-server)做改动。 + +#### 5.1 导入bus依赖 + +```xml + + org.springframework.cloud + spring-cloud-starter-bus-amqp + + + + org.springframework.boot + spring-boot-starter-actuator + +``` + +#### 5.2 修改bootstrap.yml 配置,开启总线配置,配置rabbitmq 和 开启热刷新[端点](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-actuator) + +```yml +server: + port: 8030 +spring: + application: + name: config-client + cloud: + config: + discovery: + enabled: true + # 这里我们指定的是服务名 如果配置中心有多个,且用同一个服务名,我们的客户端拉取配置的时候是负载均衡的,配置中心也就是高可用 + serviceId: config-server + # 指定分支 + label: master + # 指定环境 + profile: dev + bus: + #开启总线 + enabled: true + # 打开ack跟踪的标志(默认关闭) + trace: + enabled: true + # 使用bus实现热更新 + rabbitmq: + host: 127.0.0.1 + port: 5672 + username: guest + password: guest + + +# 注意指定注册中心的配置不要从公共配置中拉取,要在本地的配置文件中指定 +# 因为我们必须要先从注册中心去获取可用的配置中心, 然后从配置中心去拉取配置 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:8010/eureka/ + +# 暴露热刷新的端点 +management: + endpoints: + web: + exposure: + include: bus-refresh + +``` + +#### 5.3 用@RefreshScope指定需要热刷新的配置 + +```java +@Component +@ConfigurationProperties(prefix = "programmer") +@Data +@ToString +@RefreshScope // 定义下面配置热刷新范围 +public class Programmer{ + + private String name; + private int age; + private boolean married; + private Date hireDate; + private float salary; + private int random; + private Map skill; + private List company; + private School school; + +} +``` + +#### 5.4 依次启动eureka,config-server, config-client 服务 + +在client服务端启动时候,可以在控制台 看到bus 自动创建了交换机、队列等 + +``` +Created new connection: rabbitConnectionFactory#496c6d94:22/SimpleConnection@185d85d2 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 63713] +o.s.amqp.rabbit.core.RabbitAdmin : Auto-declaring a non-durable, auto-delete, or exclusive Queue (springCloudBus.anonymous.iY4TIIi9TSe0bL-TWAMhWg) durable:false, auto-delete:true, exclusive:true. It will be redeclared if the broker stops and is restarted while the connection factory is alive, but all messages will be lost. +``` + +也可以在 rabbitmq 管控台查看 + +
+ +
+ + + +#### 5.6 直接在 git 上修改配置文件,然后用 `post` 触发热刷新端点 http://localhost:8030/actuator/bus-refresh ,即可看到配置已经热刷新 + +注意: 这里的只能用 post 方式请求 ,可以用 postman 等测试软件 + +
+ +热刷新的过程在控制台有详细的打印,部分日志如下: + +```shell +# 消息传播 Attempting to connect to: [127.0.0.1:5672] Created new connection: rabbitConnectionFactory.publisher#b00f2d6:0/SimpleConnection@403c0406 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 62748] +# 从配置中心拉取配置文件 Fetching config from server at : http://DESKTOP-8JGSFLJ:8020/ +# 刷新应用上下文 AnnotationConfigApplicationContext Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@62e12f66 ``` - -http://localhost:8030/actuator/bus-refresh diff --git a/spring-cloud/spring-cloud-config/config-client/src/main/java/com/heibaiying/configclient/ConfigClientApplication.java b/spring-cloud/spring-cloud-config/config-client/src/main/java/com/heibaiying/configclient/ConfigClientApplication.java index 4b0ef35..b3ead27 100644 --- a/spring-cloud/spring-cloud-config/config-client/src/main/java/com/heibaiying/configclient/ConfigClientApplication.java +++ b/spring-cloud/spring-cloud-config/config-client/src/main/java/com/heibaiying/configclient/ConfigClientApplication.java @@ -3,11 +3,9 @@ package com.heibaiying.configclient; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @EnableDiscoveryClient -@RestController public class ConfigClientApplication { public static void main(String[] args) { diff --git a/spring-cloud/spring-cloud-config/config-client/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-config/config-client/src/main/resources/bootstrap.yml index 80f2ee8..28d046d 100644 --- a/spring-cloud/spring-cloud-config/config-client/src/main/resources/bootstrap.yml +++ b/spring-cloud/spring-cloud-config/config-client/src/main/resources/bootstrap.yml @@ -28,17 +28,13 @@ spring: # 注意指定注册中心的配置不要从公共配置中拉取,要在本地的配置文件中指定 -# 因为我们必须要先从注册中心去获取可用的配置中心, 从配置中心去拉取配置 +# 因为我们必须要先从注册中心去获取可用的配置中心, 然后从配置中心去拉取配置 eureka: client: serviceUrl: defaultZone: http://localhost:8010/eureka/ # 暴露热刷新的端点 -#management: -# endpoint: -# bus-refresh: -# enabled: true management: endpoints: web: