分布式配置中心

场景/作用总结如下:
1)集中配置管理,一个微服务架构中可能有成百上千个微服务,所以集中配置管理 是很重要的(一次修改、到处生效)
2)不同环境不同配置,比如数据源配置在不同环境(开发dev,测试test,生产prod) 中是不同的
3)运行期间可动态调整。例如,可根据各个微服务的负载情况,动态调整数据源连 接池大小等配置修改后可用动更新
4)如配置内容发生变化,微服务可以自动更新配置 那么,我们就需要对配置一件进行集中式管理,这也是分布式配置中心的作用。

Spring Cloud Config是一个分布式配置管理方案,包含了 Server端和 Client端两个 部分。
image.png
Server 端:提供配置文件的存储、以接口的形式将配置文件的内容提供出去, 通过使用 @EnableConfigServer注解在 Spring boot 应用中非常简单的嵌入
Client 端:通过接口获取配置数据并初始化自己的应用

操作如下

Config Server是集中式的配置服务,用于集中管理应用程序各个环境下的配 置。 默认使用Git存储配置文件内容,也可以SVN 。

1、在码云创建项目lagou-config-repo

2、上传yml配置文件,命名规则如下:

{application}-{profile}.yml 或者 {application}-{profile}.properties 其中,application为应用名称,profile指的是环境(用于区分开发环境,测试环境、生产环境等)
示例:lagou-service-resume-dev.yml、lagou-service-resume-test.yml、lagouservice-resume-prod.yml

3、构建Config Server统一配置中心

A、创建工程引入依赖坐标(需要注册到Eureka)

  1. <!--eureka client 客户端依赖引入-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  5. </dependency>
  6. <!--config配置中心服务端-->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-config-server</artifactId>
  10. </dependency>

B、启动类开启配置中心服务器功能

添加注解@EnableConfigServer

  1. @SpringBootApplication
  2. @EnableDiscoveryClient
  3. @EnableConfigServer // 开启配置中心功能
  4. public class ConfigServerApplication9006 {
  5. public static void main(String[] args) {
  6. SpringApplication.run(ConfigServerApplication9006.class,args);
  7. }
  8. }

C、添加配置文件

  1. server:
  2. port: 9006
  3. #注册到Eureka服务中心
  4. eureka:
  5. client:
  6. service-url:
  7. # 注册到集群,就把多个Eurekaserver地址使用逗号连接起来即可;注册到单实例(非集群模式),那就写一个就ok
  8. defaultZone: http://LagouCloudEurekaServerA:8761/eureka,http://LagouCloudEurekaServerB:8762/eureka
  9. instance:
  10. prefer-ip-address: true #服务实例中显示ip,而不是显示主机名(兼容老的eureka版本)
  11. # 实例名称: 192.168.1.103:lagou-service-resume:8080,我们可以自定义它
  12. instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
  13. spring:
  14. application:
  15. name: lagou-cloud-configserver
  16. cloud:
  17. config:
  18. server:
  19. git:
  20. uri: https://github.com/5173098004/lagou-config-repo.git #配置git服务地址
  21. username: 517309804@qq.com #配置git用户名
  22. password: yingdiangolf2010 #配置git密码
  23. search-paths:
  24. - lagou-config-repo
  25. # 读取分支
  26. label: master
  27. #针对的被调用方微服务名称,不加就是全局生效
  28. #lagou-service-resume:
  29. # ribbon:
  30. # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #负载策略调整
  31. # springboot中暴露健康检查等断点接口
  32. management:
  33. endpoints:
  34. web:
  35. exposure:
  36. include: "*"
  37. # 暴露健康接口的细节
  38. endpoint:
  39. health:
  40. show-details: always

D、将服务提供者引入配置的依赖坐标

  1. <!--Config 客户端依赖-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-config-client</artifactId>
  5. </dependency>

E、 application.yml修改为bootstrap.yml配置文件

bootstrap.yml是系统级别的,优先级高于application.yml件
是把与统一配置中心连接的配置信息放到bootstrap.yml
#############这个很重要,小弟告诉老大我要去哪里取什么东西。
根据客户端的请求,服务端会拼接,然后访问对应的仓库内容

  1. server:
  2. port: 8081
  3. spring:
  4. application:
  5. name: lagou-service-resume
  6. datasource:
  7. driver-class-name: com.mysql.jdbc.Driver
  8. url: jdbc:mysql://localhost:3306/lagou?useUnicode=true&characterEncoding=utf8
  9. username: root
  10. password: 123456
  11. jpa:
  12. database: MySQL
  13. show-sql: true
  14. hibernate:
  15. naming:
  16. physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #避免将驼峰命名转换为下划线命名
  17. #############这个很重要,小弟告诉老大我要去哪里取什么东西
  18. cloud:
  19. # config客户端配置,和ConfigServer通信,并告知ConfigServer希望获取的配置信息在哪个文件中
  20. config:
  21. name: lagou-service-resume #配置文件名称
  22. profile: dev #后缀名称
  23. label: master #分支名称
  24. uri: http://localhost:9006 #ConfigServer配置中心地址
  25. #注册到Eureka服务中心
  26. eureka:
  27. client:
  28. service-url:
  29. # 注册到集群,就把多个Eurekaserver地址使用逗号连接起来即可;注册到单实例(非集群模式),那就写一个就ok
  30. defaultZone: http://LagouCloudEurekaServerA:8761/eureka,http://LagouCloudEurekaServerB:8762/eureka
  31. instance:
  32. prefer-ip-address: true #服务实例中显示ip,而不是显示主机名(兼容老的eureka版本)
  33. # 实例名称: 192.168.1.103:lagou-service-resume:8080,我们可以自定义它
  34. instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
  35. # 自定义Eureka元数据
  36. metadata-map:
  37. cluster: cl1
  38. region: rn1
  39. management:
  40. endpoints:
  41. web:
  42. exposure:
  43. include: "*" #暴露所有的端口

4、Config配置手动刷新

不用重启微服务,只需要手动的做一⼀些其他的操作(访问一个地址/refresh)刷新, 之后再访问即可
此时,客户端取到了配置中心的值,但当我们修改GitHub上面的值时,服务端 (Config Server)能实时获取最新的值,但客户端(Config Client)读的是缓存, 无法实时获取最新值。Spring Cloud已 经为我们解决了这个问题,那就是客户端使用post去触发refresh,获取最新数据。

A、Client客户端添加依赖spring-boot-starter-actuator(已添加)

B、Client客户端bootstrap.yml中添加配置(暴露通信端点)上面已添加

C、Client客户端使用到配置信息的类ConfigController上添加@RefreshScope 注解

  1. @RestController
  2. @RequestMapping("/resume")
  3. public class ResumeController {
  4. @Autowired
  5. private ResumeService resumeService;
  6. //获取远程配置信息
  7. @Value("${server.port}")
  8. private Integer port;
  9. //"/resume/openstate/1545132"
  10. @GetMapping("/openstate/{userId}")
  11. public Integer findDefaultResumeState(@PathVariable Long userId) throws Exception {
  12. //return resumeService.findDefaultResumeByUserId(userId).getIsOpenResume();
  13. System.out.println("====>>>>>>>>>>>>>>我是8081,访问到我这里了......");
  14. return port;
  15. }
  16. }

D、 手动向Client客户端发起POST请求

http://localhost:8080/actuator/refresh, 刷新配置信息
注意:手动刷新方式避免了服务重启(流程:Git改配置—>for循环脚本手动刷新每 个微服务)

5、Config配置自动更新

在微服务架构中,我们可以结合消息总线(Bus)实现分布式配置的自动更新 (Spring Cloud Config+Spring Cloud Bus)

消息总线Bus

通过一个主题连接各个微服务,打通脉络。
Spring Cloud Bus(基于MQ的,支持RabbitMq/Kafka) 是Spring Cloud中的消息 总线方案,Spring Cloud Config + Spring Cloud Bus 结合可以实现配置信息的自动 更新。
image.png

Config+ Bus 实现自动刷新

1、 Config Server服务端添加消息总线依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  4. </dependency>

2、 ConfigServer添加配置

  1. spring:
  2. rabbitmq:
  3. host: 127.0.0.1
  4. port: 5672
  5. username: guest
  6. password: guest

3、 微服务暴露端口

  1. management:
  2. endpoints:
  3. web:
  4. exposure:
  5. include: "*" #暴露所有的端口

4、重启各个服务发送post请求

重启各个服务,更改配置之后,向配置中心服务端发送post请求
http://localhost:9003**/actuator/bus-refresh 各个客户端配置即可自动刷新 在广播模式下实现了一次请求,处处更新**。

如果我只想定向更新呢? 在发起刷新请求的时候
http://localhost:9006**/actuator/bus-refresh/lagou-serviceresume:8081 ** 即为最后跟上要定向刷新的实例的 服务名:端口号即可

5、完整配置

配置中心的application.yml

  1. server:
  2. port: 9006
  3. #注册到Eureka服务中心
  4. eureka:
  5. client:
  6. service-url:
  7. # 注册到集群,就把多个Eurekaserver地址使用逗号连接起来即可;注册到单实例(非集群模式),那就写一个就ok
  8. defaultZone: http://LagouCloudEurekaServerA:8761/eureka,http://LagouCloudEurekaServerB:8762/eureka
  9. instance:
  10. prefer-ip-address: true #服务实例中显示ip,而不是显示主机名(兼容老的eureka版本)
  11. # 实例名称: 192.168.1.103:lagou-service-resume:8080,我们可以自定义它
  12. instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
  13. spring:
  14. application:
  15. name: lagou-cloud-configserver
  16. cloud:
  17. config:
  18. server:
  19. git:
  20. uri: https://github.com/5173098004/lagou-config-repo.git #配置git服务地址
  21. username: 517309804@qq.com #配置git用户名
  22. password: yingdiangolf2010 #配置git密码
  23. search-paths:
  24. - lagou-config-repo
  25. # 读取分支
  26. label: master
  27. rabbitmq:
  28. host: 127.0.0.1
  29. port: 5672
  30. username: guest
  31. password: guest
  32. #针对的被调用方微服务名称,不加就是全局生效
  33. #lagou-service-resume:
  34. # ribbon:
  35. # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #负载策略调整
  36. # springboot中暴露健康检查等断点接口
  37. management:
  38. endpoints:
  39. web:
  40. exposure:
  41. include: "*"
  42. # 暴露健康接口的细节
  43. endpoint:
  44. health:
  45. show-details: always