Spring Cloud构建微服务架构之九 消息总线

本文参考了:
http://blog.didispace.com/springcloud7/
http://blog.didispace.com/springcloud8/

问题:如何实现对配置信息的实时更新?
虽然,我们已经能够通过/refresh接口和Git仓库的Web Hook来实现Git仓库中的内容修改触发应用程序的属性更新。但是,如果所有触发操作均需要我们手工去维护Web Hook中的应用位置的话,随着系统的不断扩张,会变的越来越难以维护,而消息代理中间件是解决该问题最为合适的方案。
消息代理有这样一个功能:消息代理中间件可以将消息路由到一个或多个目的地。利用这个功能,我们就能完美的解决该问题,下面我们来说说Spring Cloud Bus中的具体实现方案。

消息总线和RabbitMQ结合实现

RabbitMQ的基础知识和使用方法
1、简介
MQ(Message Queue)消息队列,用于应用系统解耦、消息异步分发。 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统。
其优点如下:
1)Reliability-可靠性高。
2)Flexible Routing-路由灵活。
3)Clustering-支持集群。
4)Federation-支持互联。
5)Tracing-便于追踪。
RabbitMQ的安装与使用实践。
实践环境:Window7 x64系统。
2、安装
安装Erland,通过官方下载页面http://www.erlang.org/downloads
获取exe安装包,直接打开并完成安装。
安装RabbitMQ,通过官方下载页面https://www.rabbitmq.com/download.html
获取exe安装包。
下载完成后,直接运行安装程序。
RabbitMQ Server安装完成之后,会自动的注册为服务,并以默认配置启动起来。

3、RabbitMQ启动
Rabbit管理

我们可以直接通过配置文件的访问进行管理,也可以通过Web的访问进行管理。下面我们将介绍如何通过Web进行管理。

执行rabbitmq-plugins enable rabbitmq_management命令,开启Web管理插件,这样我们就可以通过浏览器来进行管理了。

#rabbitmq-plugins enable rabbitmq_management
The following plugins have been enabled:
  mochiweb
  webmachine
  rabbitmq_web_dispatch
  amqp_client
  rabbitmq_management_agent
  rabbitmq_management
Applying plugin configuration to rabbit@SHPWSUN3... started 6 plugins.

打开浏览器并访问:http://localhost:15672/
并使用默认用户guest登录,密码也为guest。我们可以看到如下图的管理页面:

下面我们开始具体介绍Spring Cloud Bus的配置,并以一个Spring Cloud Bus与Spring Cloud Config结合的例子来实现配置内容的实时更新。

准备工作:需要用到已经实现的关于Spring Cloud Config的几个工程:
config-repo:定义在Git仓库中的一个目录,其中存储了应用名为configsample的多环境配置文件,配置文件中有一个from参数。
config-server-eureka:配置了Git仓库,并注册到了Eureka的服务端。
config-client-eureka:通过Eureka发现Config Server的客户端,应用名为configsample,用来访问配置服务器以获取配置信息。该应用中提供了一个/from接口,它会获取config-repo/configsample-dev.properties中的from属性返回。

扩展config-client-eureka应用
修改pom.xml增加spring-cloud-starter-bus-amqp模块。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
最终的POM文件如下:

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

在配置文件中增加关于RabbitMQ的连接和用户信息
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=springcloud
spring.rabbitmq.password=123456
最终配置如下:

spring.application.name=configsample

#spring.cloud.config.uri=http://localhost:7001/

server.port=7002
# 
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
#

spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
spring.cloud.config.profile=dev

management.security.enabled=false
spring.cloud.config.failFast=true

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=springcloud
spring.rabbitmq.password=123456

启动config-server-eureka,再启动两个config-client-eureka(使用不同的端口7002、7003),我们可以在config-client-eureka中的控制台中看到如下内容,在启动时候,客户端程序多了一个/bus/refresh请求。

o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/bus/refresh],methods=[POST]}" onto public void org.springframework.cloud.bus.endpoint.RefreshBusEndpoint.refresh(java.lang.String)

先访问两个config-client-eureka的/from请求,会返回当前config-repo/didispace-dev.properties中的from属性。
接着,我们修改config-repo/configsample-dev.properties中的from属性值,并发送POST请求到其中的一个/bus/refresh。
最后,我们再分别访问启动的两个config-client-eureka的/from请求,此时这两个请求都会返回最新的config-repo/configsample-dev.properties中的from属性。

到这里,我们已经能够通过Spring Cloud Bus来实时更新总线上的属性配置了。

架构优化

既然Spring Cloud Bus的/bus/refresh接口提供了针对服务和实例进行配置更新的参数,那么我们的架构也可以做出一些调整。在之前的架构中,服务的配置更新需要通过向具体服务中的某个实例发送请求,再触发对整个服务集群的配置更新。虽然能实现功能,但是这样的结果是,我们指定的应用实例就会不同于集群中的其他应用实例,这样会增加集群内部的复杂度,不利于将来的运维工作,比如:我们需要对服务实例进行迁移,那么我们不得不修改Web Hook中的配置等。所以我们要尽可能的让服务集群中的各个节点是对等的。
因此,我们将之前的架构做了一些调整,如下图所示:

在Config Server中也引入Spring Cloud Bus,将配置服务端也加入到消息总线中来。

spring.application.name=config-server
server.port=7001
# \u914D\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
# git\u4ED3\u5E93\u914D\u7F6E
spring.cloud.config.server.git.uri=https://git.coding.net/weimin/cloud.git/
spring.cloud.config.server.git.searchPaths=config-center/config-repo
spring.cloud.config.server.git.username=weimin
spring.cloud.config.server.git.password=730309

management.security.enabled=false
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=springcloud
spring.rabbitmq.password=123456

/bus/refresh请求不在发送到具体服务实例上,而是发送给Config Server,并可通过destination参数来指定需要更新配置的服务或实例。

通过上面的改动,我们的服务实例就不需要再承担触发配置更新的职责。同时,对于Git的触发等配置都只需要针对Config Server即可,从而简化了集群上的一些维护工作。

消息总线和Kafka结合实现

简介
Kafka是一个由LinkedIn开发的分布式消息系统,它于2011年初开源,现在由著名的Apache基金会维护与开发。Kafka使用Scala实现,被用作LinkedIn的活动流和运营数据处理的管道,现在也被诸多互联网企业广泛地用作为数据流管道和消息系统。

首先,我们需要从官网上下载安装介质。下载地址为:http://kafka.apache.org/downloads.html。本例中采用的版本为:Kafka-0.10.2.1

图片.png

由于Kafka的设计中依赖了ZooKeeper,所以我们可以在bin和config目录中除了看到Kafka相关的内容之外,还有ZooKeeper相关的内容。其中bin目录存放了Kafka和ZooKeeper的命令行工具,bin根目录下是适用于Linux/Unix的shell,而bin/windows下的则是适用于windows下的bat。我们可以根据实际的系统来设置环境变量,以方便后续的使用和操作。而在config目录中,则是用来存放了关于Kafka与ZooKeeper的配置信息。

然后:启动ZooKeeper,执行命令:zookeeper-server-start config/zookeeper.properties,该命令需要指定zookeeper的配置文件位置才能正确启动,kafka的压缩包中包含了其默认配置,开发与测试环境不需要修改。

图片.png
图片.png

最后:启动Kafka,执行命令:kafka-server-start config/server.properties,该命令也需要指定Kafka配置文件的正确位置,如上命令中指向了解压目录包含的默认配置。若在测试时,使用外部集中环境的ZooKeeper的话,我们可以在该配置文件中通过zookeeper.connect参数来设置ZooKeeper的地址和端口,它默认会连接本地2181端口的ZooKeeper;如果需要设置多个ZooKeeper节点,可以为这个参数配置多个ZooKeeper地址,并用逗号分割。比如:zookeeper.connect=127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002。

图片.png

创建Topic,执行命令:kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test,通过该命令,创建一个名为“test”的Topic,该Topic包含一个分区一个Replica。在创建完成后,可以使用kafka-topics --list --zookeeper localhost:2181命令来查看当前的Topic。

Kafka整合Spring Cloud Bus

上面使用Rabbit实现消息总线的案例中,我们已经通过引入spring-cloud-starter-bus-amqp模块,完成了使用RabbitMQ来实现的消息总线。若我们要使用Kafka来实现消息总线时,只需要把spring-cloud-starter-bus-amqp替换成spring-cloud-starter-bus-kafka模块,在pom.xml的dependenies节点中进行修改,具体如下:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>

如果我们在启动Kafka时均采用了默认配置,那么我们不需要再做任何其他配置就能在本地实现从RabbitMQ到Kafka的切换。

在config-server启动时,我们可以在控制台中看到如下输出:

2017-06-01 14:28:31,739  INFO main c.p.c.Application:57 - Started Application in 0.9 seconds (JVM running for 17.254)
2017-06-01 14:28:31,833  INFO main o.s.c.s.b.k.p.KafkaTopicProvisioner:106 - Using kafka topic for outbound: springCloudBus
2017-06-01 14:28:32,044  INFO main o.a.z.ZooKeeper:100 - Client environment:zookeeper.version=3.4.8--1, built on 02/06/2016 03:18 GMT
2017-06-01 14:28:32,044  INFO main o.a.z.ZooKeeper:100 - Client environment:host.name=peer1
2017-06-01 14:28:32,045  INFO main o.a.z.ZooKeeper:100 - Client environment:java.version=1.8.0_111
2017-06-01 14:28:32,045  INFO main o.a.z.ZooKeeper:100 - Client environment:java.vendor=Oracle Corporation
2017-06-01 14:28:32,045  INFO main o.a.z.ZooKeeper:100 - Client environment:java.home=C:\Programs\Java\jdk1.8.0_111\jre
2017-06-01 14:28:32,045  INFO main o.a.z.ZooKeeper:100 - Client environment:java.class.path=D:\Workspace\cloud\spring-bus\config-server-eureka-kafka\target\classes;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-config-server\1.3.0.RELEASE\spring-cloud-config-server-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-config-client\1.3.0.RELEASE\spring-cloud-config-client-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\1.5.3.RELEASE\spring-boot-autoconfigure-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-commons\1.2.0.RELEASE\spring-cloud-commons-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-context\1.2.0.RELEASE\spring-cloud-context-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-web\4.3.8.RELEASE\spring-web-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-aop\4.3.8.RELEASE\spring-aop-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-beans\4.3.8.RELEASE\spring-beans-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-context\4.3.8.RELEASE\spring-context-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-core\4.3.8.RELEASE\spring-core-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.8.0\jackson-annotations-2.8.0.jar;C:\Users\wsun3\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.8.8\jackson-databind-2.8.8.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-actuator\1.5.3.RELEASE\spring-boot-starter-actuator-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter\1.5.3.RELEASE\spring-boot-starter-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-logging\1.5.3.RELEASE\spring-boot-starter-logging-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\ch\qos\logback\logback-classic\1.1.11\logback-classic-1.1.11.jar;C:\Users\wsun3\.m2\repository\ch\qos\logback\logback-core\1.1.11\logback-core-1.1.11.jar;C:\Users\wsun3\.m2\repository\org\slf4j\jcl-over-slf4j\1.7.25\jcl-over-slf4j-1.7.25.jar;C:\Users\wsun3\.m2\repository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;C:\Users\wsun3\.m2\repository\org\slf4j\log4j-over-slf4j\1.7.25\log4j-over-slf4j-1.7.25.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-actuator\1.5.3.RELEASE\spring-boot-actuator-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-web\1.5.3.RELEASE\spring-boot-starter-web-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\1.5.3.RELEASE\spring-boot-starter-tomcat-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\8.5.14\tomcat-embed-core-8.5.14.jar;C:\Users\wsun3\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\8.5.14\tomcat-embed-el-8.5.14.jar;C:\Users\wsun3\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.14\tomcat-embed-websocket-8.5.14.jar;C:\Users\wsun3\.m2\repository\org\hibernate\hibernate-validator\5.3.5.Final\hibernate-validator-5.3.5.Final.jar;C:\Users\wsun3\.m2\repository\javax\validation\validation-api\1.1.0.Final\validation-api-1.1.0.Final.jar;C:\Users\wsun3\.m2\repository\org\jboss\logging\jboss-logging\3.3.1.Final\jboss-logging-3.3.1.Final.jar;C:\Users\wsun3\.m2\repository\com\fasterxml\classmate\1.3.3\classmate-1.3.3.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-webmvc\4.3.8.RELEASE\spring-webmvc-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-expression\4.3.8.RELEASE\spring-expression-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\security\spring-security-crypto\4.2.2.RELEASE\spring-security-crypto-4.2.2.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\security\spring-security-rsa\1.0.3.RELEASE\spring-security-rsa-1.0.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\bouncycastle\bcpkix-jdk15on\1.55\bcpkix-jdk15on-1.55.jar;C:\Users\wsun3\.m2\repository\org\bouncycastle\bcprov-jdk15on\1.55\bcprov-jdk15on-1.55.jar;C:\Users\wsun3\.m2\repository\org\eclipse\jgit\org.eclipse.jgit\4.6.0.201612231935-r\org.eclipse.jgit-4.6.0.201612231935-r.jar;C:\Users\wsun3\.m2\repository\com\jcraft\jsch\0.1.53\jsch-0.1.53.jar;C:\Users\wsun3\.m2\repository\com\googlecode\javaewah\JavaEWAH\1.1.6\JavaEWAH-1.1.6.jar;C:\Users\wsun3\.m2\repository\org\apache\httpcomponents\httpclient\4.5.3\httpclient-4.5.3.jar;C:\Users\wsun3\.m2\repository\org\apache\httpcomponents\httpcore\4.4.6\httpcore-4.4.6.jar;C:\Users\wsun3\.m2\repository\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;C:\Users\wsun3\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\Users\wsun3\.m2\repository\org\yaml\snakeyaml\1.17\snakeyaml-1.17.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-eureka\1.3.0.RELEASE\spring-cloud-starter-eureka-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter\1.2.0.RELEASE\spring-cloud-starter-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-netflix-core\1.3.0.RELEASE\spring-cloud-netflix-core-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot\1.5.3.RELEASE\spring-boot-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-netflix-eureka-client\1.3.0.RELEASE\spring-cloud-netflix-eureka-client-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\com\netflix\eureka\eureka-client\1.6.2\eureka-client-1.6.2.jar;C:\Users\wsun3\.m2\repository\org\codehaus\jettison\jettison\1.3.7\jettison-1.3.7.jar;C:\Users\wsun3\.m2\repository\stax\stax-api\1.0.1\stax-api-1.0.1.jar;C:\Users\wsun3\.m2\repository\com\netflix\netflix-commons\netflix-eventbus\0.3.0\netflix-eventbus-0.3.0.jar;C:\Users\wsun3\.m2\repository\com\netflix\netflix-commons\netflix-infix\0.3.0\netflix-infix-0.3.0.jar;C:\Users\wsun3\.m2\repository\commons-jxpath\commons-jxpath\1.3\commons-jxpath-1.3.jar;C:\Users\wsun3\.m2\repository\joda-time\joda-time\2.9.9\joda-time-2.9.9.jar;C:\Users\wsun3\.m2\repository\org\antlr\antlr-runtime\3.4\antlr-runtime-3.4.jar;C:\Users\wsun3\.m2\repository\org\antlr\stringtemplate\3.2.1\stringtemplate-3.2.1.jar;C:\Users\wsun3\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\wsun3\.m2\repository\com\google\code\gson\gson\2.8.0\gson-2.8.0.jar;C:\Users\wsun3\.m2\repository\org\apache\commons\commons-math\2.2\commons-math-2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\archaius\archaius-core\0.7.4\archaius-core-0.7.4.jar;C:\Users\wsun3\.m2\repository\javax\ws\rs\jsr311-api\1.1.1\jsr311-api-1.1.1.jar;C:\Users\wsun3\.m2\repository\com\netflix\servo\servo-core\0.10.1\servo-core-0.10.1.jar;C:\Users\wsun3\.m2\repository\com\netflix\servo\servo-internal\0.10.1\servo-internal-0.10.1.jar;C:\Users\wsun3\.m2\repository\com\sun\jersey\jersey-core\1.19.1\jersey-core-1.19.1.jar;C:\Users\wsun3\.m2\repository\com\sun\jersey\jersey-client\1.19.1\jersey-client-1.19.1.jar;C:\Users\wsun3\.m2\repository\com\sun\jersey\contribs\jersey-apache-client4\1.19.1\jersey-apache-client4-1.19.1.jar;C:\Users\wsun3\.m2\repository\com\google\inject\guice\4.1.0\guice-4.1.0.jar;C:\Users\wsun3\.m2\repository\javax\inject\javax.inject\1\javax.inject-1.jar;C:\Users\wsun3\.m2\repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;C:\Users\wsun3\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.8.8\jackson-core-2.8.8.jar;C:\Users\wsun3\.m2\repository\com\netflix\eureka\eureka-core\1.6.2\eureka-core-1.6.2.jar;C:\Users\wsun3\.m2\repository\org\codehaus\woodstox\woodstox-core-asl\4.4.1\woodstox-core-asl-4.4.1.jar;C:\Users\wsun3\.m2\repository\javax\xml\stream\stax-api\1.0-2\stax-api-1.0-2.jar;C:\Users\wsun3\.m2\repository\org\codehaus\woodstox\stax2-api\3.1.4\stax2-api-3.1.4.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-archaius\1.3.0.RELEASE\spring-cloud-starter-archaius-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\commons-configuration\commons-configuration\1.8\commons-configuration-1.8.jar;C:\Users\wsun3\.m2\repository\commons-lang\commons-lang\2.6\commons-lang-2.6.jar;C:\Users\wsun3\.m2\repository\com\google\guava\guava\18.0\guava-18.0.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-ribbon\1.3.0.RELEASE\spring-cloud-starter-ribbon-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon\2.2.2\ribbon-2.2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-transport\2.2.2\ribbon-transport-2.2.2.jar;C:\Users\wsun3\.m2\repository\io\reactivex\rxnetty-contexts\0.4.9\rxnetty-contexts-0.4.9.jar;C:\Users\wsun3\.m2\repository\io\reactivex\rxnetty-servo\0.4.9\rxnetty-servo-0.4.9.jar;C:\Users\wsun3\.m2\repository\com\netflix\hystrix\hystrix-core\1.5.10\hystrix-core-1.5.10.jar;C:\Users\wsun3\.m2\repository\org\hdrhistogram\HdrHistogram\2.1.9\HdrHistogram-2.1.9.jar;C:\Users\wsun3\.m2\repository\io\reactivex\rxnetty\0.4.9\rxnetty-0.4.9.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-codec-http\4.0.27.Final\netty-codec-http-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-codec\4.0.27.Final\netty-codec-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-handler\4.0.27.Final\netty-handler-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-transport-native-epoll\4.0.27.Final\netty-transport-native-epoll-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-common\4.0.27.Final\netty-common-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-buffer\4.0.27.Final\netty-buffer-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-transport\4.0.27.Final\netty-transport-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-core\2.2.2\ribbon-core-2.2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-httpclient\2.2.2\ribbon-httpclient-2.2.2.jar;C:\Users\wsun3\.m2\repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\netflix-commons\netflix-commons-util\0.1.1\netflix-commons-util-0.1.1.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-loadbalancer\2.2.2\ribbon-loadbalancer-2.2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\netflix-commons\netflix-statistics\0.1.1\netflix-statistics-0.1.1.jar;C:\Users\wsun3\.m2\repository\io\reactivex\rxjava\1.1.10\rxjava-1.1.10.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-eureka\2.2.2\ribbon-eureka-2.2.2.jar;C:\Users\wsun3\.m2\repository\com\thoughtworks\xstream\xstream\1.4.9\xstream-1.4.9.jar;C:\Users\wsun3\.m2\repository\xmlpull\xmlpull\1.1.3.1\xmlpull-1.1.3.1.jar;C:\Users\wsun3\.m2\repository\xpp3\xpp3_min\1.1.4c\xpp3_min-1.1.4c.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-bus-kafka\1.3.0.RELEASE\spring-cloud-starter-bus-kafka-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-stream-kafka\1.2.0.RELEASE\spring-cloud-starter-stream-kafka-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-stream-binder-kafka\1.2.0.RELEASE\spring-cloud-stream-binder-kafka-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-stream-binder-kafka-core\1.2.0.RELEASE\spring-cloud-stream-binder-kafka-core-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-stream-codec\1.2.1.RELEASE\spring-cloud-stream-codec-1.2.1.RELEASE.jar;C:\Users\wsun3\.m2\repository\com\esotericsoftware\kryo-shaded\3.0.3\kryo-shaded-3.0.3.jar;C:\Users\wsun3\.m2\repository\com\esotericsoftware\minlog\1.3.0\minlog-1.3.0.jar;C:\Users\wsun3\.m2\repository\org\objenesis\objenesis\2.1\objenesis-2.1.jar;C:\Users\wsun3\.m2\repository\org\apache\kafka\kafka_2.11\0.10.1.1\kafka_2.11-0.10.1.1.jar;C:\Users\wsun3\.m2\repository\net\sf\jopt-simple\jopt-simple\4.9\jopt-simple-4.9.jar;C:\Users\wsun3\.m2\repository\com\yammer\metrics\metrics-core\2.2.0\metrics-core-2.2.0.jar;C:\Users\wsun3\.m2\repository\org\scala-lang\scala-library\2.11.8\scala-library-2.11.8.jar;C:\Users\wsun3\.m2\repository\com\101tec\zkclient\0.9\zkclient-0.9.jar;C:\Users\wsun3\.m2\repository\org\apache\zookeeper\zookeeper\3.4.8\zookeeper-3.4.8.jar;C:\Users\wsun3\.m2\repository\io\netty\netty\3.7.0.Final\netty-3.7.0.Final.jar;C:\Users\wsun3\.m2\repository\org\scala-lang\modules\scala-parser-combinators_2.11\1.0.4\scala-parser-combinators_2.11-1.0.4.jar;C:\Users\wsun3\.m2\repository\org\apache\kafka\kafka-clients\0.10.1.1\kafka-clients-0.10.1.1.jar;C:\Users\wsun3\.m2\repository\net\jpountz\lz4\lz4\1.3.0\lz4-1.3.0.jar;C:\Users\wsun3\.m2\repository\org\xerial\snappy\snappy-java\1.1.2.6\snappy-java-1.1.2.6.jar;C:\Users\wsun3\.m2\repository\org\springframework\kafka\spring-kafka\1.1.4.RELEASE\spring-kafka-1.1.4.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\integration\spring-integration-kafka\2.1.0.RELEASE\spring-integration-kafka-2.1.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-bus\1.3.0.RELEASE\spring-cloud-bus-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-stream\1.2.1.RELEASE\spring-cloud-stream-1.2.1.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-validation\1.5.3.RELEASE\spring-boot-starter-validation-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-messaging\4.3.8.RELEASE\spring-messaging-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\integration\spring-integration-jmx\4.3.9.RELEASE\spring-integration-jmx-4.3.9.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-tuple\1.0.0.RELEASE\spring-tuple-1.0.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\integration\spring-integration-tuple\1.0.0.RELEASE\spring-integration-tuple-1.0.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\retry\spring-retry\1.2.0.RELEASE\spring-retry-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\integration\spring-integration-core\4.3.9.RELEASE\spring-integration-core-4.3.9.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-tx\4.3.8.RELEASE\spring-tx-4.3.8.RELEASE.jar
2017-06-01 14:28:32,046  INFO main o.a.z.ZooKeeper:100 - Client environment:java.library.path=C:\Programs\Java\jdk1.8.0_111\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:/Programs/Java/jre/bin/server;C:/Programs/Java/jre/bin;C:/Programs/Java/jre/lib/amd64;C:\app\wsun3\product\11.2.0\dbhome_1\bin;%JAVA_HOME%\bin;C:\ProgramData\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Enterprise Vault\EVClient\;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Windows\CCM;C:\Windows\CCM;C:\Program Files (x86)\Sennheiser\SoftphoneSDK\;C:\Program Files\WIDCOMM\Bluetooth Software\;C:\Program Files\WIDCOMM\Bluetooth Software\syswow64;C:\Programs\Git\cmd;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Programs\JavaStudio\kafka_2.10-0.10.2.1\bin\windows;C:\Programs\erl8.3\bin;C:\Python27;C:\Program Files (x86)\CVSNT\;C:\Programs\JavaStudio\sts-bundle\sts-3.8.4.RELEASE;;.
2017-06-01 14:28:32,046  INFO main o.a.z.ZooKeeper:100 - Client environment:java.io.tmpdir=C:\Users\wsun3\AppData\Local\Temp\
2017-06-01 14:28:32,046  INFO main o.a.z.ZooKeeper:100 - Client environment:java.compiler=<NA>
2017-06-01 14:28:32,046  INFO main o.a.z.ZooKeeper:100 - Client environment:os.name=Windows 7
2017-06-01 14:28:32,046  INFO main o.a.z.ZooKeeper:100 - Client environment:os.arch=amd64
2017-06-01 14:28:32,047  INFO main o.a.z.ZooKeeper:100 - Client environment:os.version=6.1
2017-06-01 14:28:32,047  INFO main o.a.z.ZooKeeper:100 - Client environment:user.name=wsun3
2017-06-01 14:28:32,047  INFO main o.a.z.ZooKeeper:100 - Client environment:user.home=C:\Users\wsun3
2017-06-01 14:28:32,047  INFO main o.a.z.ZooKeeper:100 - Client environment:user.dir=D:\Workspace\cloud\spring-bus\config-server-eureka-kafka
2017-06-01 14:28:32,048  INFO main o.a.z.ZooKeeper:438 - Initiating client connection, connectString=localhost:2181 sessionTimeout=10000 watcher=org.I0Itec.zkclient.ZkClient@45f241df
2017-06-01 14:28:32,091  INFO main-SendThread(peer1:2181) o.a.z.ClientCnxn:1032 - Opening socket connection to server peer1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
2017-06-01 14:28:32,095  INFO main-SendThread(peer1:2181) o.a.z.ClientCnxn:876 - Socket connection established to peer1/127.0.0.1:2181, initiating session
2017-06-01 14:28:32,200  INFO main-SendThread(peer1:2181) o.a.z.ClientCnxn:1299 - Session establishment complete on server peer1/127.0.0.1:2181, sessionid = 0x15c6231471c0006, negotiated timeout = 10000
2017-06-01 14:28:33,504  INFO main o.a.z.ZooKeeper:684 - Session: 0x15c6231471c0006 closed

从控制台的输出内容,我们可以看到config-server连接到了Kafka中,并使用了名为springCloudBus的Topic。

此时,我们可以使用kafka-topics --list --zookeeper localhost:2181命令来查看当前Kafka中的Topic,若已成功启动了config-server并配置正确,我们就可以在Kafka中看到已经多了一个名为springCloudBus的Topic。

我们再启动配置了spring-cloud-starter-bus-kafka模块的config-client,可以看到控制台中输出如下内容:

2017-06-01 14:34:06,716  INFO main o.s.c.s.b.k.p.KafkaTopicProvisioner:106 - Using kafka topic for outbound: springCloudBus
2017-06-01 14:34:08,044  INFO main o.a.z.ZooKeeper:100 - Client environment:zookeeper.version=3.4.8--1, built on 02/06/2016 03:18 GMT
2017-06-01 14:34:08,044  INFO main o.a.z.ZooKeeper:100 - Client environment:host.name=peer1
2017-06-01 14:34:08,044  INFO main o.a.z.ZooKeeper:100 - Client environment:java.version=1.8.0_111
2017-06-01 14:34:08,045  INFO main o.a.z.ZooKeeper:100 - Client environment:java.vendor=Oracle Corporation
2017-06-01 14:34:08,045  INFO main o.a.z.ZooKeeper:100 - Client environment:java.home=C:\Programs\Java\jdk1.8.0_111\jre
2017-06-01 14:34:08,045  INFO main o.a.z.ZooKeeper:100 - Client environment:java.class.path=D:\Workspace\cloud\spring-bus\config-client-eureka-kafka\target\classes;C:\Users\wsun3\.m2\repository\org\springframework\retry\spring-retry\1.2.0.RELEASE\spring-retry-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-core\4.3.8.RELEASE\spring-core-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-web\1.5.3.RELEASE\spring-boot-starter-web-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter\1.5.3.RELEASE\spring-boot-starter-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot\1.5.3.RELEASE\spring-boot-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\1.5.3.RELEASE\spring-boot-autoconfigure-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-logging\1.5.3.RELEASE\spring-boot-starter-logging-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\ch\qos\logback\logback-classic\1.1.11\logback-classic-1.1.11.jar;C:\Users\wsun3\.m2\repository\ch\qos\logback\logback-core\1.1.11\logback-core-1.1.11.jar;C:\Users\wsun3\.m2\repository\org\slf4j\jcl-over-slf4j\1.7.25\jcl-over-slf4j-1.7.25.jar;C:\Users\wsun3\.m2\repository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;C:\Users\wsun3\.m2\repository\org\slf4j\log4j-over-slf4j\1.7.25\log4j-over-slf4j-1.7.25.jar;C:\Users\wsun3\.m2\repository\org\yaml\snakeyaml\1.17\snakeyaml-1.17.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\1.5.3.RELEASE\spring-boot-starter-tomcat-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\8.5.14\tomcat-embed-core-8.5.14.jar;C:\Users\wsun3\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\8.5.14\tomcat-embed-el-8.5.14.jar;C:\Users\wsun3\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.14\tomcat-embed-websocket-8.5.14.jar;C:\Users\wsun3\.m2\repository\org\hibernate\hibernate-validator\5.3.5.Final\hibernate-validator-5.3.5.Final.jar;C:\Users\wsun3\.m2\repository\javax\validation\validation-api\1.1.0.Final\validation-api-1.1.0.Final.jar;C:\Users\wsun3\.m2\repository\org\jboss\logging\jboss-logging\3.3.1.Final\jboss-logging-3.3.1.Final.jar;C:\Users\wsun3\.m2\repository\com\fasterxml\classmate\1.3.3\classmate-1.3.3.jar;C:\Users\wsun3\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.8.8\jackson-databind-2.8.8.jar;C:\Users\wsun3\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.8.0\jackson-annotations-2.8.0.jar;C:\Users\wsun3\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.8.8\jackson-core-2.8.8.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-web\4.3.8.RELEASE\spring-web-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-beans\4.3.8.RELEASE\spring-beans-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-context\4.3.8.RELEASE\spring-context-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-webmvc\4.3.8.RELEASE\spring-webmvc-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-expression\4.3.8.RELEASE\spring-expression-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-aop\1.5.3.RELEASE\spring-boot-starter-aop-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-aop\4.3.8.RELEASE\spring-aop-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\aspectj\aspectjweaver\1.8.10\aspectjweaver-1.8.10.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-actuator\1.5.3.RELEASE\spring-boot-starter-actuator-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-actuator\1.5.3.RELEASE\spring-boot-actuator-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-config\1.3.0.RELEASE\spring-cloud-starter-config-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter\1.2.0.RELEASE\spring-cloud-starter-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-context\1.2.0.RELEASE\spring-cloud-context-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\security\spring-security-crypto\4.2.2.RELEASE\spring-security-crypto-4.2.2.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-commons\1.2.0.RELEASE\spring-cloud-commons-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\security\spring-security-rsa\1.0.3.RELEASE\spring-security-rsa-1.0.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\bouncycastle\bcpkix-jdk15on\1.55\bcpkix-jdk15on-1.55.jar;C:\Users\wsun3\.m2\repository\org\bouncycastle\bcprov-jdk15on\1.55\bcprov-jdk15on-1.55.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-config-client\1.3.0.RELEASE\spring-cloud-config-client-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-eureka\1.3.0.RELEASE\spring-cloud-starter-eureka-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-netflix-core\1.3.0.RELEASE\spring-cloud-netflix-core-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-netflix-eureka-client\1.3.0.RELEASE\spring-cloud-netflix-eureka-client-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\com\netflix\eureka\eureka-client\1.6.2\eureka-client-1.6.2.jar;C:\Users\wsun3\.m2\repository\org\codehaus\jettison\jettison\1.3.7\jettison-1.3.7.jar;C:\Users\wsun3\.m2\repository\stax\stax-api\1.0.1\stax-api-1.0.1.jar;C:\Users\wsun3\.m2\repository\com\netflix\netflix-commons\netflix-eventbus\0.3.0\netflix-eventbus-0.3.0.jar;C:\Users\wsun3\.m2\repository\com\netflix\netflix-commons\netflix-infix\0.3.0\netflix-infix-0.3.0.jar;C:\Users\wsun3\.m2\repository\commons-jxpath\commons-jxpath\1.3\commons-jxpath-1.3.jar;C:\Users\wsun3\.m2\repository\joda-time\joda-time\2.9.9\joda-time-2.9.9.jar;C:\Users\wsun3\.m2\repository\org\antlr\antlr-runtime\3.4\antlr-runtime-3.4.jar;C:\Users\wsun3\.m2\repository\org\antlr\stringtemplate\3.2.1\stringtemplate-3.2.1.jar;C:\Users\wsun3\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\wsun3\.m2\repository\com\google\code\gson\gson\2.8.0\gson-2.8.0.jar;C:\Users\wsun3\.m2\repository\org\apache\commons\commons-math\2.2\commons-math-2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\archaius\archaius-core\0.7.4\archaius-core-0.7.4.jar;C:\Users\wsun3\.m2\repository\javax\ws\rs\jsr311-api\1.1.1\jsr311-api-1.1.1.jar;C:\Users\wsun3\.m2\repository\com\netflix\servo\servo-core\0.10.1\servo-core-0.10.1.jar;C:\Users\wsun3\.m2\repository\com\netflix\servo\servo-internal\0.10.1\servo-internal-0.10.1.jar;C:\Users\wsun3\.m2\repository\com\sun\jersey\jersey-core\1.19.1\jersey-core-1.19.1.jar;C:\Users\wsun3\.m2\repository\com\sun\jersey\jersey-client\1.19.1\jersey-client-1.19.1.jar;C:\Users\wsun3\.m2\repository\com\sun\jersey\contribs\jersey-apache-client4\1.19.1\jersey-apache-client4-1.19.1.jar;C:\Users\wsun3\.m2\repository\org\apache\httpcomponents\httpclient\4.5.3\httpclient-4.5.3.jar;C:\Users\wsun3\.m2\repository\org\apache\httpcomponents\httpcore\4.4.6\httpcore-4.4.6.jar;C:\Users\wsun3\.m2\repository\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;C:\Users\wsun3\.m2\repository\com\google\inject\guice\4.1.0\guice-4.1.0.jar;C:\Users\wsun3\.m2\repository\javax\inject\javax.inject\1\javax.inject-1.jar;C:\Users\wsun3\.m2\repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;C:\Users\wsun3\.m2\repository\com\netflix\eureka\eureka-core\1.6.2\eureka-core-1.6.2.jar;C:\Users\wsun3\.m2\repository\org\codehaus\woodstox\woodstox-core-asl\4.4.1\woodstox-core-asl-4.4.1.jar;C:\Users\wsun3\.m2\repository\javax\xml\stream\stax-api\1.0-2\stax-api-1.0-2.jar;C:\Users\wsun3\.m2\repository\org\codehaus\woodstox\stax2-api\3.1.4\stax2-api-3.1.4.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-archaius\1.3.0.RELEASE\spring-cloud-starter-archaius-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\commons-configuration\commons-configuration\1.8\commons-configuration-1.8.jar;C:\Users\wsun3\.m2\repository\commons-lang\commons-lang\2.6\commons-lang-2.6.jar;C:\Users\wsun3\.m2\repository\com\google\guava\guava\18.0\guava-18.0.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-ribbon\1.3.0.RELEASE\spring-cloud-starter-ribbon-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon\2.2.2\ribbon-2.2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-transport\2.2.2\ribbon-transport-2.2.2.jar;C:\Users\wsun3\.m2\repository\io\reactivex\rxnetty-contexts\0.4.9\rxnetty-contexts-0.4.9.jar;C:\Users\wsun3\.m2\repository\io\reactivex\rxnetty-servo\0.4.9\rxnetty-servo-0.4.9.jar;C:\Users\wsun3\.m2\repository\com\netflix\hystrix\hystrix-core\1.5.10\hystrix-core-1.5.10.jar;C:\Users\wsun3\.m2\repository\org\hdrhistogram\HdrHistogram\2.1.9\HdrHistogram-2.1.9.jar;C:\Users\wsun3\.m2\repository\io\reactivex\rxnetty\0.4.9\rxnetty-0.4.9.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-codec-http\4.0.27.Final\netty-codec-http-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-codec\4.0.27.Final\netty-codec-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-handler\4.0.27.Final\netty-handler-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-transport-native-epoll\4.0.27.Final\netty-transport-native-epoll-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-common\4.0.27.Final\netty-common-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-buffer\4.0.27.Final\netty-buffer-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\io\netty\netty-transport\4.0.27.Final\netty-transport-4.0.27.Final.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-core\2.2.2\ribbon-core-2.2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-httpclient\2.2.2\ribbon-httpclient-2.2.2.jar;C:\Users\wsun3\.m2\repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\netflix-commons\netflix-commons-util\0.1.1\netflix-commons-util-0.1.1.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-loadbalancer\2.2.2\ribbon-loadbalancer-2.2.2.jar;C:\Users\wsun3\.m2\repository\com\netflix\netflix-commons\netflix-statistics\0.1.1\netflix-statistics-0.1.1.jar;C:\Users\wsun3\.m2\repository\io\reactivex\rxjava\1.1.10\rxjava-1.1.10.jar;C:\Users\wsun3\.m2\repository\com\netflix\ribbon\ribbon-eureka\2.2.2\ribbon-eureka-2.2.2.jar;C:\Users\wsun3\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\Users\wsun3\.m2\repository\com\thoughtworks\xstream\xstream\1.4.9\xstream-1.4.9.jar;C:\Users\wsun3\.m2\repository\xmlpull\xmlpull\1.1.3.1\xmlpull-1.1.3.1.jar;C:\Users\wsun3\.m2\repository\xpp3\xpp3_min\1.1.4c\xpp3_min-1.1.4c.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-bus-kafka\1.3.0.RELEASE\spring-cloud-starter-bus-kafka-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-starter-stream-kafka\1.2.0.RELEASE\spring-cloud-starter-stream-kafka-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-stream-binder-kafka\1.2.0.RELEASE\spring-cloud-stream-binder-kafka-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-stream-binder-kafka-core\1.2.0.RELEASE\spring-cloud-stream-binder-kafka-core-1.2.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-stream-codec\1.2.1.RELEASE\spring-cloud-stream-codec-1.2.1.RELEASE.jar;C:\Users\wsun3\.m2\repository\com\esotericsoftware\kryo-shaded\3.0.3\kryo-shaded-3.0.3.jar;C:\Users\wsun3\.m2\repository\com\esotericsoftware\minlog\1.3.0\minlog-1.3.0.jar;C:\Users\wsun3\.m2\repository\org\objenesis\objenesis\2.1\objenesis-2.1.jar;C:\Users\wsun3\.m2\repository\org\apache\kafka\kafka_2.11\0.10.1.1\kafka_2.11-0.10.1.1.jar;C:\Users\wsun3\.m2\repository\net\sf\jopt-simple\jopt-simple\4.9\jopt-simple-4.9.jar;C:\Users\wsun3\.m2\repository\com\yammer\metrics\metrics-core\2.2.0\metrics-core-2.2.0.jar;C:\Users\wsun3\.m2\repository\org\scala-lang\scala-library\2.11.8\scala-library-2.11.8.jar;C:\Users\wsun3\.m2\repository\com\101tec\zkclient\0.9\zkclient-0.9.jar;C:\Users\wsun3\.m2\repository\org\apache\zookeeper\zookeeper\3.4.8\zookeeper-3.4.8.jar;C:\Users\wsun3\.m2\repository\io\netty\netty\3.7.0.Final\netty-3.7.0.Final.jar;C:\Users\wsun3\.m2\repository\org\scala-lang\modules\scala-parser-combinators_2.11\1.0.4\scala-parser-combinators_2.11-1.0.4.jar;C:\Users\wsun3\.m2\repository\org\apache\kafka\kafka-clients\0.10.1.1\kafka-clients-0.10.1.1.jar;C:\Users\wsun3\.m2\repository\net\jpountz\lz4\lz4\1.3.0\lz4-1.3.0.jar;C:\Users\wsun3\.m2\repository\org\xerial\snappy\snappy-java\1.1.2.6\snappy-java-1.1.2.6.jar;C:\Users\wsun3\.m2\repository\org\springframework\kafka\spring-kafka\1.1.4.RELEASE\spring-kafka-1.1.4.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\integration\spring-integration-kafka\2.1.0.RELEASE\spring-integration-kafka-2.1.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-bus\1.3.0.RELEASE\spring-cloud-bus-1.3.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\cloud\spring-cloud-stream\1.2.1.RELEASE\spring-cloud-stream-1.2.1.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\boot\spring-boot-starter-validation\1.5.3.RELEASE\spring-boot-starter-validation-1.5.3.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-messaging\4.3.8.RELEASE\spring-messaging-4.3.8.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\integration\spring-integration-jmx\4.3.9.RELEASE\spring-integration-jmx-4.3.9.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-tuple\1.0.0.RELEASE\spring-tuple-1.0.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\integration\spring-integration-tuple\1.0.0.RELEASE\spring-integration-tuple-1.0.0.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\integration\spring-integration-core\4.3.9.RELEASE\spring-integration-core-4.3.9.RELEASE.jar;C:\Users\wsun3\.m2\repository\org\springframework\spring-tx\4.3.8.RELEASE\spring-tx-4.3.8.RELEASE.jar
2017-06-01 14:34:08,100  INFO main o.a.z.ZooKeeper:100 - Client environment:java.library.path=C:\Programs\Java\jdk1.8.0_111\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:/Programs/Java/jre/bin/server;C:/Programs/Java/jre/bin;C:/Programs/Java/jre/lib/amd64;C:\app\wsun3\product\11.2.0\dbhome_1\bin;%JAVA_HOME%\bin;C:\ProgramData\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Enterprise Vault\EVClient\;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Windows\CCM;C:\Windows\CCM;C:\Program Files (x86)\Sennheiser\SoftphoneSDK\;C:\Program Files\WIDCOMM\Bluetooth Software\;C:\Program Files\WIDCOMM\Bluetooth Software\syswow64;C:\Programs\Git\cmd;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Programs\JavaStudio\kafka_2.10-0.10.2.1\bin\windows;C:\Programs\erl8.3\bin;C:\Python27;C:\Program Files (x86)\CVSNT\;C:\Programs\JavaStudio\sts-bundle\sts-3.8.4.RELEASE;;.
2017-06-01 14:34:08,100  INFO main o.a.z.ZooKeeper:100 - Client environment:java.io.tmpdir=C:\Users\wsun3\AppData\Local\Temp\
2017-06-01 14:34:08,101  INFO main o.a.z.ZooKeeper:100 - Client environment:java.compiler=<NA>
2017-06-01 14:34:08,102  INFO main o.a.z.ZooKeeper:100 - Client environment:os.name=Windows 7
2017-06-01 14:34:08,102  INFO main o.a.z.ZooKeeper:100 - Client environment:os.arch=amd64
2017-06-01 14:34:08,102  INFO main o.a.z.ZooKeeper:100 - Client environment:os.version=6.1
2017-06-01 14:34:08,103  INFO main o.a.z.ZooKeeper:100 - Client environment:user.name=wsun3
2017-06-01 14:34:08,104  INFO main o.a.z.ZooKeeper:100 - Client environment:user.home=C:\Users\wsun3
2017-06-01 14:34:08,104  INFO main o.a.z.ZooKeeper:100 - Client environment:user.dir=D:\Workspace\cloud\spring-bus\config-client-eureka-kafka
2017-06-01 14:34:08,106  INFO main o.a.z.ZooKeeper:438 - Initiating client connection, connectString=localhost:2181 sessionTimeout=10000 watcher=org.I0Itec.zkclient.ZkClient@3f267e1b
2017-06-01 14:34:08,161  INFO main-SendThread(peer1:2181) o.a.z.ClientCnxn:1032 - Opening socket connection to server peer1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
2017-06-01 14:34:08,164  INFO main-SendThread(peer1:2181) o.a.z.ClientCnxn:876 - Socket connection established to peer1/127.0.0.1:2181, initiating session
2017-06-01 14:34:08,208  INFO main-SendThread(peer1:2181) o.a.z.ClientCnxn:1299 - Session establishment complete on server peer1/127.0.0.1:2181, sessionid = 0x15c6231471c000a, negotiated timeout = 10000
2017-06-01 14:34:09,074  INFO main o.a.z.ZooKeeper:684 - Session: 0x15c6231471c000a closed

可以看到,config-client启动时输出了类似的内容,他们都订阅了名为springCloudBus的Topic。

在启动了config-server和config-client之后,为了更明显地观察消息总线刷新配置的效果,我们可以在本地启动多个不同端口的config-client。此时,我们的config-server以及多个config-client都已经连接到了由Kafka实现的消息总线上。我们可以先访问各个config-client上的/from请求,查看他获取到的配置内容。然后,修改Git中对应的参数内容,再访问各个config-client上的/from请求,可以看到配置内容并没有改变。最后,我们向config-server发送POST请求:/bus/refresh,此时我们再去访问各个config-client上的/from请求,就能获得到最新的配置信息,各客户端上的配置都已经加载为最新的Git配置内容。

从config-client的控制台中,我们可以看到如下内容:

2017-06-01 14:43:19,196  INFO -L-1 o.s.c.b.e.RefreshListener:44 - Received remote refresh request. Keys refreshed [from]
2017-06-01 14:43:20,604  INFO -L-1 o.s.c.b.e.RefreshListener:44 - Received remote refresh request. Keys refreshed [from]

RefreshListener监听类记录了收到远程刷新请求,并刷新了from属性的日志。

完整示例:spring-bus

推荐阅读更多精彩内容