Spring cloud config server如果不结合Spring cloud bus,那么就无法实现动态更新,只能重启服务才能生效新的配置,比如我们的注册服务器(Eureka)是整个Spring cloud系统中的单点风险,在正常运营过程中或测试环境切换到正式环境时,我们准备了两套注册服务器,希望在这两者之间不停机进行动态切换。
Spring cloud bus支持RabbitMQ和Kafka两种方式,RabbitMQ安装需要先安装erlang,linux和windows下erlang安装方式不一样,linux下需要源码编译,如果缺失组件需要升级,会折腾半天,而Kafka直接下载压缩包用Java命令启动即可,且支持事务性消息,其日志方式的机制更灵活强大,可以根据CAP定理在高可用性和高一致性灵活选择,当然用在配置更新方面是可用性重要还是一致性重要,这与注册服务器考量原则是一样的,服务注册一定是注重高可用性,而不是高一致性,如果这个问题不考虑清楚,设计再强大的分布式注册框架也是走错方向。配置更新方面使用异步总线其实已经是一种最终一致性,但是这种最终一致性也不能不一致时间太长,否则影响功能正常运行,比如1000个服务中已经有800个服务改变到新的注册服务器配置,而其他200个还没有,在这种情况下,两者之间存在相互找不到对方,网络存在分区了,业务上是否容许?当然Kafka会将这种不一致延迟降低到最低。
废话少说,Spring cloud配置服务器和其客户端之间通讯如果系统通过Spring cloud bus很简单,只要在pom.xml增加:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-kafka</artifactId> </dependency>
然后在服务端的application .properties中加入:
spring.cloud.bus.enabled=true spring.kafka.bootstrap-servers=localhost:9092
激活bus通讯,默认是关闭的。告知Kafka的服务器地址。
下面我们需要激活动态刷新功能,这个过程有点小复杂,Spring cloud不同版本变化有点大,首先,在服务器端我们要引入actuator
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator</artifactId> </dependency>
actuator在Spring 2.0以后改变很大,我们为了调用其刷新url :/actuator/bus-refresh,需要将其暴露,在application.properties配置:
management.endpoints.web.exposure.include=*
我们在上一篇使用Oracle作为我们配置信息存储库的案例,如果数据库中配置信息更改,我们通过主动post刷新配置服务器的/actuator/bus-refresh将新的配置信息广播给相关者,这里我们还是使用前面几篇一个应用用例,微服务需要指导注册服务器的地址,这个地址信息我们存储到配置服务器的Oracle中,当我们想切换注册服务器的IP地址时,通过Spring cloud bus+kafka通知各个微服务。
在配置服务器三步配置,第一步pom.xml:
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc8</artifactId> <version>12.2.0.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-kafka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
在application.properties配置:
spring.application.name=config-server-jdbc server.port=8888 spring.profiles.active=jdbc spring.datasource.url=jdbc:oracle:thin:@//localhost:1521/pengpdborcl spring.datasource.username=scottpeng spring.datasource.password=scottpeng spring.cloud.config.label=master spring.cloud.bus.enabled=true spring.kafka.bootstrap-servers=localhost:9092 management.endpoints.web.exposure.include=*
第二段是有关将Oracle作为配置存储库,第三段有关bus总线配置,第三段也就是最后一样是有关主动刷新的。
以上是Spring cloud config服务器端配置,那么客户端也就是需要向注册服务器注册自身的微服务怎么配置?只要加上pom.xml:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-kafka</artifactId> </dependency>
如果Kafka是在默认localhost:9092就不需要配置了,否则要配置spring.kafka.bootstrap-servers=XXX:9092
这就是客户端的配置了,好了,我们现在试验运行。
首先运行好eureka注册服务器,启动kafka,然后启动Spring cloud config server,然后再启动客户端Producer的应用,它的注册服务器配置信息:
#eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
需要通过配置服务器获得,这条信息保存在oracle数据库中:
如果我们更换注册服务器ip地址从localhost:1111更换到localhost:1112,当然我们也要事先启动eureka在1112端口:
java -jar - Dserver.port=1112 registry-0.0.1-SNAPSHOT.jar
通过localhost:1111和localhost:1112可以发现,在前者页面发现有一个PengProducerService注册其中,后者没有,那么如果将数据库中localhost:1111更换到localhost:1112,然后用post方式访问/actuator/bus-refresh主动刷新这一变动:
在配置服务器控制台立即出现:
Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7688c373: startup date [Sun Jul 15 21:57:11 CST 2018]; root of context hierarchy
表示配置服务器端刷新激活,在客户端Producer控制台则出现:
Received remote refresh request. Keys refreshed []
表示都已经激活新的配置,再访问localhost:1111和localhost:1112可以发现,可以发现PengProducerService已经更换注册地了。
本文源码: 百度网盘
spring cloud专题