springcloud之配置中心git

隨着線上項目變的日益龐大,每個項目都散落着各種配置文件,如果採用分佈式的開發模式,需要的配置文件隨着服務增加而不斷增多。某一個基礎服務信息變更,都會引起一系列的更新和重啓,運維苦不堪言也容易出錯。

配置中心便是解決此類問題的靈丹妙藥。

市面上開源的配置中心有很多,BAT每家都出過,360的QConf、淘寶的diamond、百度的disconf都是解決這類問題。

國外也有很多開源的配置中心Apache Commons Configuration、owner、cfg4j等等。

這裏要講的是Spring Cloud Config,它功能全面強大,可以無縫的和spring體系相結合。

Spring Cloud Config

在我們瞭解spring cloud config之前,我可以想想一個配置中心提供的核心功能應該有什麼

  • 提供服務端和客戶端支持
  • 集中管理各環境的配置文件
  • 配置文件修改之後,可以快速的生效
  • 可以進行版本管理
  • 支持大的併發查詢
  • 支持各種語言

Spring Cloud Config可以完美的支持以上所有的需求。

Spring Cloud Config項目是一個解決分佈式系統的配置管理方案它包含了Client和Server兩個部分,server提供配置文件的存儲、以接口的形式將配置文件的內容提供出去,client通過接口獲取數據、並依據此數據初始化自己的應用。Spring cloud使用git或svn存放配置文件,默認情況下使用git,我們先以git爲例做一套示例。

首先在github上面創建了一個文件夾config-repo用來存放配置文件,爲了模擬生產環境,我們創建以下三個配置文件:

// 開發環境
neo-config-dev.properties
// 測試環境
neo-config-test.properties
// 生產環境
neo-config-pro.properties

每個配置文件中都寫一個屬性neo.hello,屬性值分別是 hello im dev/test/pro 。

neo.hello=hello im dev

下面我們開始配置server端

server 端

1、添加依賴

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
</dependencies>

只需要加入spring-cloud-config-server包引用既可。

2、配置文件

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:                                             # git倉庫的賬號
          password:                                             # git倉庫的密碼

Spring Cloud Config也提供本地存儲配置的方式。

我們只需要設置屬性spring.profiles.active=nativeConfig Server會默認從應用的src/main/resource目錄下檢索配置文件

也可以通過 spring.cloud.config.server.native.searchLocations=file:E:/properties/屬性來指定配置文件的位置。雖然Spring Cloud Config提供了這樣的功能,但是爲了支持更好的管理內容和版本控制的功能,還是推薦使用git的方式

3、啓動類

啓動類添加 @EnableConfigServer,激活對配置中心的支持

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

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

到此server端相關配置已經完成

4、測試

首先我們先要測試server端是否可以讀取到github上面的配置信息,直接訪問:http://localhost:8001/neo-config/dev

返回信息如下:

{
    "name": "neo-config", 
    "profiles": [
        "dev"
    ], 
    "label": null, 
    "version": null, 
    "state": null, 
    "propertySources": [
        {
            "name": "https://github.com/ityouknow/spring-cloud-starter/config-repo/neo-config-dev.properties", 
            "source": {
                "neo.hello": "hello im dev"
            }
        }
    ]
}

上述的返回的信息包含了配置文件的位置版本配置文件的名稱以及配置文件中的具體內容,說明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 端

主要展示如何在業務項目中去獲取server端的配置信息

1、添加依賴

<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>

引入spring-boot-starter-web包方便web測試

2、配置文件

需要配置兩個配置文件,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。

3、啓動類

 

@SpringBootApplication
public class ConfigClientApplication {

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

4、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

Spring Cloud Config分服務端和客戶端,服務端負責將git(svn)中存儲的配置文件發佈成REST接口,客戶端可以從服務端REST接口獲取配置。但客戶端並不能主動感知到配置的變化,從而主動去獲取新的配置。客戶端如何去主動獲取新的配置信息呢,

springcloud已經給我們提供瞭解決方案,每個客戶端通過POST方法觸發各自的/refresh

修改spring-cloud-config-client項目已到達可以refresh的功能。

1、添加依賴

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

增加了spring-boot-starter-actuator包,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;
    }
}

3、測試

springboot 1.5.X 以上默認開通了安全認證,所以需要在配置文件application.properties添加以下配置

management.security.enabled=false

OK 這樣就改造完了,以post請求的方式來訪問 http://localhost:8002/refresh 就會更新修改後的配置文件。

我們再次來測試,首先訪問http://localhost:8002/hello,返回:hello im dev,我將庫中的值修改爲hello im dev update

在win上面打開cmd執行curl -X POST http://localhost:8002/refresh,返回["neo.hello"]說明已經更新了neo.hello的值。

我們再次訪問http://localhost:8002/hello,返回:hello im dev update,客戶端已經得到了最新的值。

每次手動刷新客戶端也很麻煩,有沒有什麼辦法只要提交代碼就自動調用客戶端來更新呢,github的webhook是一個好的辦法。

4、webhook

WebHook是當某個事件發生時,通過發送http post請求的方式來通知信息接收方。

Webhook來監測你在Github.com上的各種事件,最常見的莫過於push事件。

如果你設置了一個監測push事件的Webhook,那麼每當你的這個項目有了任何提交,這個Webhook都會被觸發

這時Github就會發送一個HTTP POST請求到你配置好的地址。

  如此一來,你就可以通過這種方式去自動完成一些重複性工作,比如,你可以用Webhook來自動觸發一些持續集成(CI)工具的運作,比如Travis CI;又或者是通過 Webhook 去部署你的線上服務器。下圖就是github上面的webhook配置。

  • Payload URL :觸發後回調的URL
  • Content type 數據格式,兩種一般使用json
  • Secret 用作給POST的body加密的字符串。採用HMAC算法
  • events 觸發的事件列表
events事件類型描述
push 倉庫有push時觸發。默認事件
create 當有分支或標籤被創建時觸發
delete 當有分支或標籤被刪除時觸發

svn也有類似的hook機制,每次提交後會觸發post-commit腳本,我們可以在這裏寫一些post請求

這樣我們就可以利用hook的機制去觸發客戶端的更新,但是當客戶端越來越多的時候hook支持的已經不夠優雅,另外每次增加客戶端都需要改動hook也是不現實的。其實Spring Cloud給了我們更好解決方案,後面文章來介紹。

參考網址

配置中心使用svn的示例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章