接上一篇的Spring-Cloud-Config 配置中心的应用(一),上一篇中说过了单机版的配置中心,所有的连接都是直接用IP的,如果配置中心集群化继续使用IP就很繁琐了,所以就需要将其服务化,也就是注册到Eureka中,通过Eureka调度。
服务化
案例实践
本案例使用Spring-Cloud Hoxton.SR5 版本
引入依赖
在config-server、config-client中将Eureka的客户端依赖引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件
在config-server配置文件application.yml
中加入Eureka的配置
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka/
在config-client配置文件bootstrap.yml
中加入Eureka配置以及改变连接config-server的配置
spring:
cloud:
config:
name: config
profile: dev
label: master
discovery:
enabled: true
service-id: spring-cloud-config-server
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka/
在两个启动类中都加入开启Eureka客户端发现服务注解@EnableDiscoveryClient
测试服务化
将Eureka、config-server、config-client依次启动,访问config-client的hello
接口http://localhost:9001/hello/myconfig
可以得到和我们之前通过IP连接config-server一样的配置。
config-server集群测试
将config-server的端口改为10001
,再启动一个server服务(启动方式参考#idea多实例启动),重新访问我们的hello
接口,可以正常得到我们的配置信息。然后随机停掉一台config-server服务,因为我们的client是有本地缓存的,为了检验集群是否可用我们还要把配置信息更新,并发起POST请求刷新缓存http://localhost:9001/actuator/refresh
。刷新之后再次访问我们的hello
接口,再次得到了我们最新的配置信息,这说明我们的集群配置OK的。
使用Spring-Cloud-Bus
配置中心集群化了,但是我们的客户端还是单机的,如果也要集群化,那么很简单也换个端口再启动一个就好,但是有一个问题,如果要刷新缓存我们需要调用所以的客户端的接口一个一个的刷新,那这不得把人逼疯?所以这时我们就需要一个Spring-Cloud-Bus这样一个消息总线来达到一处刷新处处刷新的效果。
Spring-Cloud-Bus的本质是利用了MQ的广播机制在分布式的系统中传播消息,目前常用的有Kafka和RabbitMQ。
案例实践
本案例使用Spring-Cloud Hoxton.SR5 版本
MQ使用的是RabbitMQ
引入依赖
config-client服务中引入下面的mq依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
配置文件
config-client的bootstrap.yml
文件中修改为
spring:
cloud:
config:
name: config
profile: dev
label: master
discovery:
enabled: true
service-id: spring-cloud-config-server
rabbitmq:
port: 5672
username: admin
password: 123456
host: 192.168.0.104
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka/
management:
endpoints:
web:
exposure:
include: '*'
多加入了MQ的配置
docker启动RabbitMQ
使用RabbitMQ还需要一个RabbitMQ的客户端,可以去RabbitMQ的官网下载一个客户端或者使用docker启动一个RabbitMQ的镜像,这里我选择了使用docker来启动RabbitMQ,既学习了RabbitMQ,又学习了docker。
docker run --rm -d --hostname rabbitmq --name rabbitmq -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123456 rabbitmq
测试消息总线
将修改过的服务重启,并修改端口号多启动几个,比如再启动9002
、9003
、9004
。访问http://localhost:9001/hello/myconfig
,可以正常获取到配置信息,访问其他的几个端口也可以获取到配置信息。
现在将配置信息更新,调用http://localhost:9001/actuator/bus-refresh
刷新所有的客户端的配置缓存。执行完后,再次访问hello
接口就可以看到,所有所有客户端的配置都已更新。
优化刷新方式
上述的刷新是通过访问客户端的/actuator/bus-refresh
端口来执行刷新,但是客户端有时候会经常的发生变化,那么这种情况下,我们可以考虑将客户端刷新改为服务端的刷新,然后再由bus
去通知各个客户端获取最新的配置达到刷新缓存的目的。
引入依赖
服务端引入下面的mq依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
配置文件
config-client的bootstrap.yml
文件中修改为
server:
port: 10000
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://gitee.com/bennettChina/spring-cloud-demo.git
search-paths: config-repo
username:
password:
rabbitmq:
host: 192.168.0.104
port: 5672
username: admin
password: 123456
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka/
management:
endpoints:
web:
exposure:
include: '*'
多加入了MQ的配置以及暴露bus-refresh
端口(这里直接暴露了所有的端口)
测试服务端刷新
将服务端重启后,访问我们的hello
接口,可以获取到我们的配置信息。将配置信息更新后,这次选择调用服务端的/actuator/bus-refresh
端口进行刷新,POST请求http://localhost:10000/actuator/bus-refresh
后,重新调用hello
接口,可以发现所有的客户端也都实现了配置更新。
局部刷新
某些场景下(例如灰度发布),我们可能只想刷新部分微服务的配置,此时可通过/actuator/bus-refresh
端点的destination
参数来定位要刷新的应用程序。
例如:/actuator/bus-refresh?destination=customers:8000
,这样消息总线上的微服务实例就会根据destination参数的值来判断是否需要要刷新。其中,customers:8000
指的是各个微服务的ApplicationContext ID(默认是指{spring.application.name}:{server.port}
)。
destination
参数也可以用来定位特定的微服务。例如:/actuator/bus-refresh?destination=customers:**
,这样就可以触发customers微服务所有实例的配置刷新。
SpringCloud的配置中心到这里也就分享完了。
文章参考
纯洁的微笑:配置中心和消息总线
SpringCloud中文网:Spring-Cloud-Config