1. 程式人生 > >SpringCloud 配置中心Config和訊息匯流排Bus

SpringCloud 配置中心Config和訊息匯流排Bus

一、概述

二、Config

三、Refresh

四、配置中心服務化

五、基於Webhook和訊息匯流排的解決方案

一、概述

SpringCloud配置中心包括Config和Bus兩個組成部分,只要這樣,才能保證主動推送。

下面主要分為四個部分,

Config講了基本的配置中心,但這樣如果修改配置客戶端在執行中是無法改變的。

Refresh講了我們修改配置檔案後可以向客戶端傳送一個POST請求,可以利用WebHook的方式。

配置中心服務化講了我們把配置中心獨立成一個服務(最好多掛幾個)掛到Eureka

基於Webhook和訊息匯流排的解決方案,讓我們客戶端可以實時的感知配置變化,從而做出改邊。

我們先看Config,然後整合Bus來達到我們配置中心的目的。

二、Config

1.Config概述

當一個系統配置檔案修改,我們需要重啟系統,但是微服務狀態下系統數量太多,為了方便服務配置檔案統一管理,實時更新,所以需要分散式配置中心元件。在Spring Cloud中,有分散式配置中心元件spring cloud config ,它支援配置服務放在配置服務的記憶體中(即本地),也支援放在遠端Git倉庫中。在spring cloud config 元件中,分兩個角色,一是config server,二是config client。

引入spring cloud config後,我們的外部配置檔案就可以集中放置在一個git倉庫裡,再新建一個config server,用來管理所有的配置檔案,維護的時候需要更改配置時,只需要在本地更改後,推送到遠端倉庫,所有的服務例項都可以通過config server來獲取配置檔案,這時每個服務例項就相當於配置服務的客戶端config client,為了保證系統的穩定,配置服務端config server可以進行叢集部署,即使某一個例項,因為某種原因不能提供服務,也還有其他的例項保證服務的繼續進行。

2.示例

⑴server

①新增依賴

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-server</artifactId>
	</dependency>
</dependencies>
②配置檔案
server:
  port: 8001
spring:
  application:
    name: spring-cloud-config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/cGitHub123/Springcloud.git     # 配置git倉庫的地址
          search-paths: config-repo                             # git倉庫地址下的相對地址,可以配置多個,用,分割。
          username:                                              # git倉庫的賬號
          password:                                              # git倉庫的密碼

Spring Cloud Config也提供本地儲存配置的方式。我們只需要設定屬性spring.profiles.active=native,Config Server會預設從應用的src/main/resource目錄下檢索配置檔案。也可以通過spring.cloud.config.server.native.searchLocations=file:E:/properties/屬性來指定配置檔案的位置。雖然Spring Cloud Config提供了這樣的功能,但是為了支援更好的管理內容和版本控制的功能,還是推薦使用git的方式。

③啟動類
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigServerApplication.class, args);
	}
}
④測試

返回值:

{
    "name": "neo-config", 
    "profiles": [
        "dev"
    ], 
    "label": null, 
    "version": null, 
    "state": null, 
    "propertySources": [
        {
            "name": "https://github.com/cGitHub123/Springcloud.git/config-repo/neo-config-dev.properties", 
            "source": {
                "neo.hello": "hello im dev update"
            }
        }
    ]
}
上述的返回的資訊包含了配置檔案的位置、版本、配置檔案的名稱以及配置檔案中的具體內容,說明server端已經成功獲取了git倉庫的配置資訊。


如果直接檢視配置檔案中的配置資訊可訪問:http://localhost:8001/neo-config-dev.properties,返回:neo.hello: hello im dev

修改配置檔案neo-config-dev.properties中配置資訊為:neo.hello=hello im dev update,再次在瀏覽器訪問http://localhost:8001/neo-config-dev.properties,返回:neo.hello: hello im dev update。說明server端會自動讀取最新提交的內容

倉庫中的配置檔案會被轉換成web介面,訪問可以參照以下的規則:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
以neo-config-dev.properties為例子,它的application是neo-config,profile是dev。client會根據填寫的引數來選擇讀取對應的配置。

⑵Client端

①新增依賴

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-config</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-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>
②配置檔案

需要配置兩個配置檔案,application.properties和bootstrap.properties

application.properties如下:

spring.application.name=spring-cloud-config-client
server.port=8002
bootstrap.properties如下:
spring.cloud.config.name=neo-config
spring.cloud.config.profile=dev
spring.cloud.config.uri=http://localhost:8001/
spring.cloud.config.label=master
spring.application.name:對應{application}部分
spring.cloud.config.profile:對應{profile}部分
spring.cloud.config.label:對應git的分支。如果配置中心使用的是本地儲存,則該引數無用
spring.cloud.config.uri:配置中心的具體地址
spring.cloud.config.discovery.service-id:指定配置中心的service-id,便於擴充套件為高可用配置叢集。
特別注意:上面這些與spring-cloud相關的屬性必須配置在bootstrap.properties中,config部分內容才能被正確載入。因為config的相關配置會先於application.properties,而bootstrap.properties的載入也是先於application.properties。

③啟動類

@SpringBootApplication
public class ConfigClientApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigClientApplication.class, args);
	}
}

④Web測試

使用@Value註解來獲取server端引數的值

@RestController
class HelloController {
    @Value("${neo.hello}")
    private String hello;

    @RequestMapping("/hello")
    public String from() {
        return this.hello;
    }
}
啟動專案後訪問:http://localhost:8002/hello,返回:hello im dev update說明已經正確的從server端獲取到了引數。到此一個完整的服務端提供配置服務,客戶端獲取配置引數的例子就完成了。

我們在進行一些小實驗,手動修改neo-config-dev.properties中配置資訊為:neo.hello=hello im dev update1提交到github,再次在瀏覽器訪問http://localhost:8002/hello,返回:neo.hello: hello im dev update,說明獲取的資訊還是舊的引數,這是為什麼呢?因為springboot專案只有在啟動的時候才會獲取配置檔案的值,修改github資訊後,client端並沒有在次去獲取,所以導致這個問題。如何去解決這個問題呢?

三、Refresh

為了解決上面的問題,我們修改Client端,我們一修改配置,就給客戶端發個POST請求,我們不但要解決上面問題,還要讓客戶端主動感知提交的程式碼從而主動的更新:

1.新增依賴

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

spring-boot-starter-actuator是一套監控的功能,可以監控程式在執行時狀態,其中就包括/refresh的功能。

2.開啟更新機制

需要給載入變數的類上面載入@RefreshScope,在客戶端執行/refresh的時候就會更新此類下面的變數值。

@RestController
@RefreshScope // 使用該註解的類,會在接到SpringCloud配置中心配置重新整理的時候,自動將新的配置更新到該類對應的欄位中。
class HelloController {

    @Value("${neo.hello}")
    private String hello;

    @RequestMapping("/hello")
    public String from() {
        return this.hello;
    }
}

在這種模式下,我們先請求服務端

http://localhost:8001/neo-config-dev.properties
返回:
neo.hello: hello im dev update

然後我們請求客戶端

http://localhost:8002/hello
返回:
hello im dev update bus
我們手動修改配置檔案,請求服務端:
neo.hello: hello im dev update bus edit

這時候我們手動執行:

curl -X POST http://localhost:8002/bus/refresh

請求客戶端:

neo.hello: hello im dev update bus edit

四、配置中心服務化

1.服務端改造

⑴新增依賴

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-server</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
	</dependency>
</dependencies>
⑵配置檔案
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8000/eureka/   ## 註冊中心eurka地址
⑶啟動類

啟動類新增@EnableDiscoveryClient啟用對配置中心的支援

@EnableDiscoveryClient
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigServerApplication.class, args);
	}
}
然後我們啟動一個Eureka服務,再啟動上面的啟動類,可以看到已經註冊上去了,這裡我們可以將服務端改為高可用模式

2.客戶端改造

⑴新增依賴

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-config</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>
⑵配置檔案
spring.application.name=spring-cloud-config-client
server.port=8002

spring.cloud.config.name=neo-config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=spring-cloud-config-server

eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
主要是去掉了spring.cloud.config.uri直接指向server端地址的配置,增加了最後的三個配置:

spring.cloud.config.discovery.enabled :開啟Config服務發現支援
spring.cloud.config.discovery.serviceId :指定server端的name,也就是server端spring.application.name的值
eureka.client.serviceUrl.defaultZone :指向配置中心的地址
這三個配置檔案都需要放到bootstrap.properties的配置中

⑶啟動類

啟動類新增@EnableDiscoveryClient啟用對配置中心的支援

@EnableDiscoveryClient
@SpringBootApplication
public class ConfigClientApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigClientApplication.class, args);
	}
}
啟動client端,在瀏覽器中訪問:http://localhost:8000/ 就會看到server端和client端都已經註冊了到註冊中心了。

五、基於Webhook和訊息匯流排的解決方案

1.基本原理圖



這時Spring Cloud Bus做配置更新步驟如下:

⑴提交程式碼觸發post請求給bus/refresh

server端接收到請求併發送給Spring Cloud Bus

⑶Spring Cloud bus接到訊息並通知給其它客戶端

⑷其它客戶端接收到通知,請求Server端獲取最新配置

⑸全部客戶端均獲取到最新的配置

2.客戶端

⑴新增依賴

需要多引入spring-cloud-starter-bus-amqp包,增加對訊息匯流排的支援

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
⑵修改配置檔案
## 重新整理時,關閉安全驗證
management.security.enabled=false
## 開啟訊息跟蹤
spring.cloud.bus.trace.enabled=true

spring.rabbitmq.host=192.168.9.89
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456
3.服務端

⑴新增依賴

需要多引入spring-cloud-starter-bus-amqp包,增加對訊息匯流排的支援

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-server</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-bus-amqp</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
	</dependency>
</dependencies>
⑵修改配置檔案
server:
  port: 8001
spring:
  application:
    name: spring-cloud-config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/ityouknow/spring-cloud-starter/     # 配置git倉庫的地址
          search-paths: config-repo                             # git倉庫地址下的相對地址,可以配置多個,用,分割。
          username: username                                        # git倉庫的賬號
          password: password                                    # git倉庫的密碼
  rabbitmq:
    host: 192.168.0.6
    port: 5672
    username: admin
    password: 123456

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8000/eureka/   ## 註冊中心eurka地址


management:
  security:
     enabled: false   //配置檔案要注意格式,要不無效!!!

4.測試

我們將github上的檔案

neo.hello=hello im dev update bus edit edit 
改成:
neo.hello=hello im dev update bus edit edit zuizhong

然後執行一個CURL:

curl -X POST http://localhost:8001/bus/refresh
然後讀8001(配置伺服器端):
http://localhost:8001/neo-config-dev.properties
顯示:
neo.hello: hello im dev update bus edit edit zuizhong
然後我們讀:

8002客戶端:

http://localhost:8002/hello
輸出:
hello im dev update bus edit edit zuizhong
8003客戶端:
http://localhost:8003/hello
輸出:
hello im dev update bus edit edit zuizhong