本系列筆記涉及到的代碼在GitHub上,地址:https://github.com/zsllsz/cloud
本文涉及知識點:
服務(wù)配置中心之config;
服務(wù)消息總線之bus(會用到rabbitmq);
歡迎大家關(guān)注我的公眾號 javawebkf,目前正在慢慢地將簡書文章搬到公眾號,以后簡書和公眾號文章將同步更新,且簡書上的付費文章在公眾號上將免費。
一、服務(wù)配置中心之springCloud Config
1、是什么?
springCloud學到現(xiàn)在,已經(jīng)新建了十四五個module,每個module都有yml,不方便管理,所以配置中心就應(yīng)運而生了。我們可以把微服務(wù)相同的配置抽到配置中心里面去,比如數(shù)據(jù)源的配置。假如某一天需要換數(shù)據(jù)源,只需要修改配置中心的配置即可,而不用每個微服務(wù)的yml都去改。沒錯,以前學的zookeeper也有這功能。spring config 分為服務(wù)端和客戶端兩部分,服務(wù)端也稱分布式配置中心,是一個獨立的微服務(wù)應(yīng)用;客戶端則是通過指定的配置中心來管理應(yīng)用資源以及業(yè)務(wù)相關(guān)的配置內(nèi)容,并在啟動的時候從配置中心加載配置信息。
2、能干嘛?
- 集中管理配置文件
- 不同環(huán)境不同配置,動態(tài)化的配置更新,分環(huán)境部署
- 運行期間動態(tài)調(diào)整配置
- 配置發(fā)生變化時不需要重啟即可使用新的配置
- 將配置信息以rest接口形式暴露
3、config服務(wù)端配置與測試:
- 首先在github上新建一個倉庫,然后新建一個config-dev.yml文件,內(nèi)容隨意,如下圖:

- 新建名為cloud-config-center-3344的module;
- pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator </artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
- yml:
server:
port: 3344
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
uri: git@github.com:zsllsz/springcloud-config.git # github倉庫地址
search-paths:
- springcloud-config # 搜索目錄
label: master # 讀取的分支
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka
- 主啟動:
@SpringBootApplication
@EnableConfigServer
public class ConfigMain3344 {
public static void main(String[] args) throws Exception {
SpringApplication.run(ConfigMain3344.class, args);
}
}
啟動后7001注冊中心,然后啟動3344,訪問http://localhost:3344/master/config-dev.yml,看看能否讀取到config-dev.yml中的內(nèi)容:

如果讀取的是master,那么http://localhost:3344/master/config-dev.yml中的master可以省略,因為默認就是讀master;如果讀其他分支,比如dev,那就在配置中寫成dev,然后訪問的url將master換成dev即可。url還可以是這樣:http://localhost:3344/config/dev/master,這里表示讀取config-dev文件,分支為master。如果用lable表示分支,application表示文件名,profiles表示環(huán)境,那么url形式有如下幾種:
- /lable/application-profile.yml
- /application-profile.yml(只能讀master)
- /application/profile/lable
4、config客戶端配置與測試:
- 修改github上的config-dev.yml,將內(nèi)容改成符合yml文件格式的內(nèi)容,比如這樣:
- 新建名為cloud-config-client-3355的module;
- pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator </artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
- bootstrap.yml:注意,以前的yml是application.yml,它是用戶級的資源配置,現(xiàn)在要新建一個bootstrap.yml,這個是系統(tǒng)級的,優(yōu)先級更高。
server:
port: 3355
spring:
application:
name: config-client
# config 配置
cloud:
config:
label: master # 分支
name: config # 文件名
profile: dev # 環(huán)境
# 以上三個組合起來就是表示讀取master上的config-dev.yml
uri:
- http://localhost:3344 # 配置中心地址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka
- 主啟動:
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3355 {
public static void main(String[] args) throws Exception {
SpringApplication.run(ConfigClientMain3355.class, args);
}
}
- controller:
@RestController
@RequestMapping("/config")
public class ConfigController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/info")
public String getInfo() {
return configInfo;
}
}
我們在bootstrap.yml中配置了配置中心3344的訪問路徑,3344又會去github上找config-dev.yml,這個文件上又有config.info,所以在這個controller直接用@Value注解可以獲取。最后訪問這個controller,就可以在瀏覽器輸出config-dev.yml中config.info的信息,如下:

5、動態(tài)刷新問題:
加入github上的config-dev.yml內(nèi)容修改了,3344因為是直接連接github去獲取配置信息的,所以可以獲取最新信息;但是3355就必須重啟才能獲取最新內(nèi)容,這不方便。接下來配置動態(tài)刷新,即不用重啟也可以獲取最新配置:
- 修改bootstrap.yml,加上如下配置:
# 暴露監(jiān)控端口
management:
endpoints:
web:
exposure:
include:
- "*"
- 在controller中加上@RefreshScope注解,如下:
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/info")
public String getInfo() {
return configInfo;
}
}
這樣就搞定了,可以修改github上文件測試一下。經(jīng)實測訪問3355時還是沒有獲取到最新的配置內(nèi)容,其實還需要發(fā)送一個post請求刷新3355。執(zhí)行如下命令或者用postman請求都可:
curl -X POST "http://localhost:3355/actuator/refresh"
二、服務(wù)消息總線之springcloud bus
上面的config還有點麻煩的就是每次修改了github上的配置文件,想要客戶端也能立即讀取到最新的,需要發(fā)送一個post請求去刷新,總歸還是不方便。springcloud bus就是對springcloud config的增強,配合config使用,可以實現(xiàn)完全自動刷新,不需要再發(fā)post請求。
1、是什么?
搭配消息中間件使用,可以實現(xiàn)全局廣播通知。支持的消息中間件有RabbitMQ和Kafka。這個消息總線就像一個微信公眾號,一個個的微服務(wù)應(yīng)用就是訂閱了這個公眾號的人。微信公眾號發(fā)了推文,每個訂閱了的人都可以收到消息。這個springcloud bus就是這個公眾號,它會讓所有的服務(wù)都連接上來,配置文件有變化它會通知所有的服務(wù)。
2、RabbitMQ安裝與配置:
- 由于RabbitMQ是Erlang語言開發(fā)的,所以要安裝Erlang,在centos上依次執(zhí)行以下命令即可安裝erlang:
yum install -y epel-release
wget https://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
rpm -Uvh erlang-solutions-1.0-1.noarch.rpm
yum install -y erlang
erl -version
- rabbitmq的安裝:首先下載rpm包,地址:https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.3/rabbitmq-server-3.8.3-1.el7.noarch.rpm,然后執(zhí)行如下命令:
# 導入密鑰
rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc
# 安裝
yum install rabbitmq-server-3.8.3-1.el7.noarch.rpm
# 啟動
systemctl start rabbitmq-server
# 開啟圖形界面
rabbitmq-plugins enable rabbitmq_management
訪問ip:15672,即可訪問圖形界面。默認用戶名和密碼都為guest,但是這個只允許用localhost訪問,所以可以通過以下步驟新建用戶:
# 新建admin用戶,密碼也為admin
rabbitmqctl add_user admin admin
# 設(shè)置權(quán)限
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
# 將admin設(shè)置為管理員用戶
rabbitmqctl set_user_tags admin administrator
# 重啟rabbitmq
systemctl restart rabbitmq-server
再次訪問ip:15672,用admin就可以登陸進去了。

3、springcloud bus的使用:
- 新建名為cloud-config-client-3366的module;
- pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator </artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
- bootstrap.yml:
server:
port: 3366
spring:
application:
name: config-client
# config 配置
cloud:
config:
label: master # 分支
name: config # 文件名
profile: dev # 環(huán)境
# 以上三個組合起來就是表示讀取master上的config-dev.yml
uri:
- http://localhost:3344 # 配置中心地址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka
# 暴露監(jiān)控端點
management:
endpoints:
web:
exposure:
include:
- "*"
- 主啟動類:
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3366 {
public static void main(String[] args) throws Exception {
SpringApplication.run(ConfigClientMain3366.class, args);
}
}
- controller:
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/info")
public String getInfo() {
return configInfo;
}
}
上面還沒用到bus。bus的通知思想有兩種,一種是廣播通知一個客戶端,進而通知到所有的客戶端;另一種是bus廣播通知服務(wù)端,服務(wù)端再通知所有的客戶端。一般情況使用第二種方式,即通知服務(wù)端,通知這個帶頭大哥即可。
下面開始使用springcloud bus
- 修改3344的pom,新增如下依賴:
<!-- rabbitmq的支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
- 修改3344的yml,添加rabbitmq和bus相關(guān)配置,如下:
# mq相關(guān)配置
rabbitmq:
host: 192.168.0.106
port: 5672
username: admin
password: admin
# bus配置
management:
endpoints:
web:
exposure:
include:
- 'bus-refresh'
- 修改3355的pom,添加如下依賴:
<!-- rabbitmq的支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
- 修改3355的yml,添加如下配置:
# mq相關(guān)配置
rabbitmq:
host: 192.168.0.106
port: 5672
username: admin
password: admin
- 3366和3355做一樣的修改。
- 依次啟動7001,3344,3355,3366
- 3344、3355和3366先訪問一次配置文件
- 然后修改github上config-dev.yml的內(nèi)容
- 3344此時可以訪問到修改后的內(nèi)容,因為它是帶頭大哥,直連github的,但是3355和3366此時還沒有獲取到最新的,因為RabbitMQ還沒進行廣播通知;
- 執(zhí)行如下命令:
curl -X POST http://localhost:3344/actuator/bus-refresh
- 刷新了帶頭大哥3344,叫它去通知3355和3366,再次去訪問3355和3366,發(fā)現(xiàn)也能獲取到最新的配置了。這就是bus和rabbitmq的功勞。如下圖,在rabbitmq上有一個topic叫springCloudBus,3344、3355和3366都訂閱了這個topic。當github上的配置發(fā)生改變時,我們就發(fā)一個post請求去通知3344,然后所有訂閱了該topic的服務(wù)都會收到通知去更新配置。

4、定點通知:
上面演示的是通知所有訂閱了該topic的服務(wù),即3355和3366都通知到了。如果我想只通知3355,又當如何?發(fā)送post請求的時候指定發(fā)給誰就行了,公式就是:
curl -X POST http://localhost:3344/actuator/bus-refresh/客戶端的服務(wù)名:服務(wù)端口
服務(wù)名就是config客戶端的微服務(wù)名字,即3344和3355的spring.application.name,比如只通知3355,那么執(zhí)行如下命令即可:
curl -X POST http://localhost:3344/actuator/bus-refresh/config-client:3355