6. SpringCloud之ConfigServer配置中心以及Bus消息总线

目录

1、分布式配置中心解决了什么问题?

  1. 配置信息的外部统一管理。
  2. 做到系统的高可用,修改了配置文件后可在各个服务 动态刷新,不需要重启服务器。

2、架构图

image.png

3、在git上创建配置文件

这里为了演示,只创建 订单服务需要的配置

在master分支 ,项目下方 创建config目录, 下面创建一个订单 服务 dev环境的配置文件

micro-order-dev.properties :

格式注意一下, 要为 {服务名}-{profiles} ,服务名为 micro-order,配置文件环境为dev

image.png

配置内容为 :

username=wangxiaoer

4、Springcloud 配置中心服务端

4.1、新建一个Springboot配置中心子工程

image.png

4.2、导入依赖

引入配置中心服务端的依赖,

引入eureka客户端的依赖,配置中心服务端同样需要 注册到注册中心,让需要拉取配置的其他服务发现他。


    org.springframework.cloud
    spring-cloud-config-server



    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-client

4.3、启动类

加上@EnableConfigServer,开启配置中心功能

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

4.4、bootstrap.properties配置

# 端口号
server.port=9002
# 服务名,其他服务 根据服务名 从配置中心服务 拉取配置
spring.application.name=config-server
# 由于配置信息要统一放到git上, 需要配置git
# 拉取配置的仓库地址
spring.cloud.config.server.git.uri=https://git.lug.ustc.edu.cn/liuben/celebrity-cloud.git
# 配置文件放在哪个目录,我们把配置文件放在了config下,这里就配置为config文件夹
spring.cloud.config.server.git.searchPaths=config
# 分支
spring.cloud.config.label=master
# 用户名和密码
spring.cloud.config.server.git.username=****
spring.cloud.config.server.git.password=****

# 注册到 注册中心
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://localhost:9001/eureka/

4.5、启动配置中心服务端 工程

image.png

通过启动日志可以看到,配置中心服务端创建了很多接口,这些接口可以对数据加密/解密 ,直接查看 配置中心服务 所拉取到的配置信息。

查看 配置信息的 接口 有很多种格式,大抵都是由 label,和 name,和profiles 这几个变量 来构成的

  1. label : 对应代码分支

  2. name : 对应服务名

  3. profiles : 对应不同环境的配置文件

这里我们访问 /{label}/{name}-{profiles}.properties 这种格式的

master分支,订单工程 micro-order,配置文件环境 dev ,所以我们在浏览器这样访问:

http://localhost:9101/master/micro-order-dev.properties 
image.png

可以看到,配置中心服务端服务 已经从git上拉取到了 config目录下micro-order-dev.properties的配置信息。

5、配置中心客户端配置

改造订单服务从 配置中心服务端拉取配置

5.1、引入 配置中心 客户端 依赖


    org.springframework.cloud
    spring-cloud-starter-config

5.2、服务内配置文件更改

将application改成 bootstrap

文件名更改,要从application.properties 改成 bootstrap.properties。

bootstrap的配置优先级更高, bootstrap文件 由父ApplicationContext加载,比application优先加载,主要用于从额外的资源来加载配置信息。

否则用application.properties,那么会从默认的8888端口去拉取配置中心服务的配置。会在移动时报以下错误:

Spring Cloud 服务启动连接 报:Fetching config from server at : http://localhost:8888

5.3、bootstrap.properties 配置 从 配置中心拉取配置

这样配置的意图 就是 从配置中心 拉取 master分支下的 micro-order-dev.properties/yml 的 配置信息,

其他分支 /其他服务 / 其他环境 /的配置不会拉取

spring.application.name=micro-order
#spring.cloud.controller.uri= http://localhost:9009/
server.port=9011
#eureka.client.service-url.defaultZone=http://localhost:9001/eureka/
eureka.client.serviceUrl.defaultZone=http://admin:admin@localhost:9001
eureka.instance.health-check-url-path=/actuator/health

#  配置 从 配置中心拉取配置信息
# 分支为master
spring.cloud.config.label=master
# 环境为dev
spring.cloud.config.profile=dev
spring.cloud.config.discovery.enabled=true
# 服务名为 配置中心服务的服务名 : config-server
spring.cloud.config.discovery.serviceId=config-server

5.4、启动

启动时,会从配置中心服务 拉取自己服务的配置

image.png

5.5、测试当前服务是否成功拉取到配置

编写一个controller:

@RequestMapping
@RestController
public class ConfigController {

    @Value("${username}")
    private String username;

    @GetMapping("/getUsername")
    public String getUsername() {
        return username;
    }
}

调用订单服务的getUsername接口,看 username这个配置 是否 加载成功

image.png

结果 是 成功 获取 到 了 git上配置的 username 这个 配置。

6、SpringCloudConfig客户端快速失败和重试

6.1、快速失败

当客户端连配置中心服务端失败时,客户端就快速失败,不进行加载其他的 spring 容器

bootstrap.properties配置:

#如果连接不上获取配置有问题,快速响应失败
spring.cloud.config.fail-fast=true

6.2、重试机制

1、导入重试功能依赖:


    org.springframework.retry
    spring-retry

2、bootstrap.properties配置:

#默认重试的间隔时间,默认 1000ms
spring.cloud.config.retry.multiplier=1000
#下一间隔时间的乘数,默认是 1.1
#spring.cloud.config.retry.initial-interval=1.1
#最大间隔时间,最大 2000ms
spring.cloud.config.retry.max-interval=2000
#最大重试次数,默认 6 次
spring.cloud.config.retry.max-attempts=6

7、配置信息的加密

在配置中心中,有些信息是比较敏感的,比如密码信息,在配置密码信息的时候有必要对密 码信息加密以免密码信息泄露,springcloud 配置中心也支持配置信息加密的,这里用 RSA 非对称加密举例。

7.1、本地生成秘钥

cd 到 jdk 的 keytool 目录:D:\Program Files\Java\jdk1.8.0_92\jre\bin 里面有一个 keytool.exe 可执行文件

7.2、执行指令生成秘钥文件

keytool -genkeypair -alias config-server -keyalg RSA -keystore config-server.keystore -validity 365

期间会让你输入密码和密钥等相关信息, 指令执行成功后会在 bin 目录生成一个 config-server.keystore 文件,把该文件 copy 到配置中 心服务工程中 resources 目录下。

7.3、配置中心服务端 配置

properties 配置文件添加秘钥配置

#加密配置
encrypt.key-store.location=config-server.keystore
encrypt.key-store.alias=config-server
# 生成config-server.keystore 设置的 密码和密钥 都是123456
encrypt.key-store.password=123456
encrypt.key-store.secret=123456

pom 中添加静态文件扫描,让能够扫描到.keystore 文件


    
        
            src/main/resources
            
                **/*.properties
                **/*.keystore
            
            false
        
    

7.4、密码加密和解密接口

在配置中心服务端中有提供对信息加密和解密接口的

7.4.1、加密接口:

http://localhost:8085/encrypt,post 请求 
image.png

body 中 输入 明文 123456 加密接口 返回密文。

7.4.2、解密接口:

localhost:9101//decrypt
image.png

body中 输入 密文 ,返回解密后的 明文

说明加密解密的相关配置 是 没问题的。

7.5、代码仓库密文配置

我们对刚才git上的配置信息 配置密文

再密文前面加上 {cipher}前缀, 通知服务端解密, 后面跟着 密文

image.png

重启配置中心服务端和订单服务后,再调之前的接口

image.png

可以发现, 订单服务获取到 的 是 解密之后的明文。

8、配置动态加载刷新

这个是一个革命性的功能,在运行期修改配置文件后,我们通过这个动态刷新功能可以不重 启服务器,这样我们系统理论上可以保证 7*24 小时的工作。

8.1、Environment 的动态刷新

动态刷新其实要有一个契机,其实这个契机就是手动调用刷新接口,如果你想刷新哪台主机 的配置,就调用哪台主机的刷新接口。

# 刷新接口为:主机ip+端口 /actuator/refresh post请求
http://localhost:9011/actuator/refresh

前提是当前服务 得 引入了 服务监控包。


    org.springframework.boot
    spring-boot-starter-actuator

并且暴露所有接口,比如 health,info, refresh。

# 暴露 actuator包 下的所有接口
management.endpoints.web.exposure.include=*

调用接口 :

image.png

调这个接口 会通知 配置中心服务端 从 git上 拉取最新的配置, 然后 当前主机 又可以从配置中心服务端的 获取到 最新的配置, 最终 刷新系统内的 配置信息。

接口会返回 有变化的配置 的key。

8.2、@Value 注入的属性动态刷新

其实前面在调用刷新接口后,@Value 注入的属性是没有刷新的还是老的配置,这个也好理 解,@Value 注入的属性是项目启动就已经定了的。如果要使@Value 属性也刷新,就必须要 在类上面加上:@RefreshScope 注解 。

@RefreshScope 其实就是个 bean作用域的注解 , 调用接口 会使bean的作用域结束,然后这个bean重新创建注册到spring容器中,引用到 配置信息的 字段 也会从 最新的配置信息 中 赋上新值。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
// refresh作用域
@Scope("refresh")
@Documented
public @interface RefreshScope {
    ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}

但是调用每台主机的刷新接口显然太麻烦了,如果需要刷新的集群机器有几百台,是不是就 需要手动调用几百次呢,这几乎是一个不能完成的工作量。 Springcloud 中也提供了消息总线的东西,借助 mq 来完成消息的广播,当需要刷新时我们就 只要调用一次刷新接口即可。

9、消息总线

消息总线其实很简单,就是为了解决一点刷新的功能,在一个点调用请求刷新接口,然后所 有的在消息总线中的端点都能接到刷新的消息,所有我们必须把每一个端点都拉入到消息总 线中来。

9.1、导入依赖

导入SpringcloudBus 的依赖


    org.springframework.cloud
    spring-cloud-starter-bus-amqp

9.2、properties 配置

这个配置 配置到 配置中心 和 自己服务下 都可以

# 其实就是连接 mq 的配置
spring.rabbitmq.host=连接rabbitmq的ip
spring.rabbitmq.port=连接rabbitmq的端口
spring.rabbitmq.username=连接rabbitmq的用户名
spring.rabbitmq.password=连接rabbitmq的密码
# 刷新配置 url http://localhost:9011/actuator/bus-refresh
spring.cloud.bus.refresh.enabled=true
spring.cloud.bus.trace.enabled=true

通过这两步就已经完成了拉入消息总线的工作了

如果要刷新配置,就只要调用任意一个消息总线端点调用刷新接口即可,其他的端点就会收 到刷新配置的消息。

刷新接口:

http://localhost:9011/actuator/bus-refresh

9.3、消息总线原理

开启了消息总线的服务,启动时会 连接rabbitmq , 创建 并消费 消息队列(自动删除,排他的 )。rabbitmq中会被注册一个统一的Topic类型的交换机。消息总线的端点创建的队列都会绑定这个交换机 ,路由键为 # ,统配所有消息格式。

当某个端点调用 /actuator/bus-refresh 接口时, 会往这个交换机发消息, 交换机将消息广播到 消息总线端点绑定的所有队列, 所有队列的 消费者(也就是所有消息总线的服务端点)消费到 消息 后 刷新 配置消息。

9.3.1、消息总线注册的交换机

image.png

9.3.2、消息总线端点 绑定的队列

image.png

9.3.3、队列与 交换机的路由键

image.png

9.4、利用github -webhook 更改配置信息 自动调用

这个接口也可以配置到 GitHub 中,只要 GitHub 有代码变更,就会调用这个接口。

到git仓库里设置 webhook

image.png

当然这里配置的 URL 是你生产环境的外网地址,这样当你 GitHub 中修改了配置后,就会主 动调用消息总线的刷新接口。

9.5、消息总线的弊端

消息总线弊端就是太重了,一个集群通知刷新配置功能,还得用一个 rabbitmq 来做,如果 项目中根本用不到 rabbitmq 呢?就加大了项目负担,加大了维护成本。

你可能感兴趣的:(6. SpringCloud之ConfigServer配置中心以及Bus消息总线)