一。spring-cloud-bus是什么瘤缩?
回答這個(gè)問(wèn)題之前,我們先回顧先前的分布式配置,當(dāng)配置中心發(fā)生變化后伯病,我們需要利用spring-boot-actuator里的refresh端點(diǎn)進(jìn)行手動(dòng)刷新:
根據(jù)上述示例情況:我們每次要獲取最新配置時(shí),要一個(gè)一個(gè)的通過(guò)refresh刷新服務(wù)節(jié)點(diǎn)否过,這種方式是不是非常low而且非常麻煩午笛,那該怎么辦呢?
大家還記得zookeeper中watch是做什么用的嗎苗桂?當(dāng)監(jiān)控的節(jié)點(diǎn)數(shù)據(jù)發(fā)生變化了药磺,那么是不是所有訂閱到該節(jié)點(diǎn)的客戶(hù)端都會(huì)觸發(fā)一個(gè)訂閱回調(diào)呢?這其實(shí)也類(lèi)似于我們的消息總線(xiàn)煤伟。在微服務(wù)架構(gòu)的系統(tǒng)中癌佩,我們通常會(huì)使用輕量級(jí)的消息代理來(lái)構(gòu)建一個(gè)公有的消息主題讓系統(tǒng)中所有微服務(wù)實(shí)例都連接上來(lái),由于該主題中產(chǎn)生的消息會(huì)被所有實(shí)例監(jiān)聽(tīng)和消費(fèi)便锨,所以我們稱(chēng)它為消息總線(xiàn)围辙。
那么在分布式配置中,我們的所有服務(wù)都訂閱消息總線(xiàn)的話(huà)放案,當(dāng)配置改變時(shí)姚建,配置中心通知消息總線(xiàn),然后所有的服務(wù)節(jié)點(diǎn)接收到訂閱消息后吱殉,在從配置中心獲取最新的配置掸冤,是不是一個(gè)一勞永逸的過(guò)程?那么可以得到如下結(jié)構(gòu)圖:
二友雳、實(shí)現(xiàn)分布式配置的消息總線(xiàn)
我先貼出:項(xiàng)目結(jié)構(gòu)圖
我們統(tǒng)一把配置放在config目錄下
1稿湿、在對(duì)應(yīng)的服務(wù)添加對(duì)應(yīng)的依賴(lài)
首先我們先配置config-server。gradle配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jayuan</groupId>
<artifactId>config-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-server</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-streams</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</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-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
注意我們使用kafka作為消息總線(xiàn)的中間件
然后我們依次在所需的服務(wù)中添加對(duì)應(yīng)的依賴(lài)
View Code
2沥阱、配置對(duì)應(yīng)的application.yml
config-server的yml文件:
View Code
這里面注意要把端點(diǎn)先開(kāi)放出來(lái)缎罢,然后進(jìn)行kafka的相關(guān)配置,其余服務(wù)的配置文件也進(jìn)行這樣的操作考杉,使其能與消息總線(xiàn)通訊策精。
3、依次啟動(dòng)服務(wù)
當(dāng)服務(wù)啟動(dòng)成功時(shí)崇棠,SpringBootActuator給我們提供一個(gè)/bus/refresh端點(diǎn)咽袜,同時(shí)我們可以在kafka主題里面找到相應(yīng)的topics,其名字為springCloudBus:4、訪(fǎng)問(wèn)Config-Server的/bus/refesh
我們先使用kafka的消費(fèi)端來(lái)監(jiān)聽(tīng)一下消息內(nèi)容枕稀。運(yùn)行:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Kite One", sans-serif; font-size: 12px !important;"> ./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic springCloudBus</pre>
緊接著我們?cè)谠L(fǎng)問(wèn) http://localhost:8888/bus/refresh 刷新config-server的配置
然后我們可以發(fā)現(xiàn)消費(fèi)端询刹,訂閱到如下消息:
其中:type為消息的事件類(lèi)型
timestamp 為消息的時(shí)間戳
orginService:消息的來(lái)源服務(wù)實(shí)例
destinationService:消息的目標(biāo)服務(wù)實(shí)例谜嫉,**代表了總線(xiàn)上的所有服務(wù)實(shí)例
在本例子中,我們可以看到每個(gè)服務(wù)的ackId都來(lái)自于 type為RefreshRemoteApplicationEvent的服務(wù)ID
5凹联、運(yùn)行服務(wù)
我們先通過(guò)gradle的build任務(wù)進(jìn)行打包會(huì)得到如下文件:xxxx.jar與xxx.jar.orginal
那么進(jìn)入到對(duì)應(yīng)目錄下 啟動(dòng)兩個(gè)服務(wù)并注冊(cè)到注冊(cè)中心 命令如下:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Kite One", sans-serif; font-size: 12px !important;">java -Dserver.port=8300 -Dspring.profiles.active=local -jar xxxx.jar
java -Dserver.port=8200 -Dspring.profiles.active=local -jar xxxx.jar</pre>
注意一定不要在application.yml配置如上參數(shù)沐兰,否則通過(guò)(-Dxxx=xxx)系統(tǒng)變量設(shè)置的值將不會(huì)生效
此時(shí)我們更改config對(duì)應(yīng)的配置并commit后,在運(yùn)行步驟4蔽挠,就可以拿到最新的結(jié)果了住闯,再次附上相關(guān)代碼:
StudentConfig:
View Code
order-server-local:
View Code