(七)Spring Cloud 配置中心config

  • 2020 年 4 月 10 日
  • 筆記

 

spring cloud config是一個基於http協議的遠程配置實現方式。

通過統一的配置管理伺服器進行配置管理,客戶端通過http協議主動的拉取服務的的配置資訊,完成配置獲取。

 

下面我們對spring cloud config配置中心進行搭建

主要有以下模組

eureka-server 服務註冊中心

eureka-config config配置中心

eureka-config-resp1  git遠程倉庫,用於存儲客戶端的配置文件

eureka-client1 客戶端1,它的配置從config配置中心讀取

eureka-client2 客戶端2,它的配置從config配置中心讀取

 

 1. eureka-server註冊中心

   1.1 eureka-server pom 文件

    

<?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 https://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.2.5.RELEASE</version>          <relativePath/> <!-- lookup parent from repository -->      </parent>      <groupId>com.devin</groupId>      <artifactId>eureka-server</artifactId>      <version>0.0.1-SNAPSHOT</version>      <name>eureka-server</name>      <description>Demo project for Spring Boot</description>        <properties>          <java.version>1.8</java.version>          <spring-cloud.version>Hoxton.SR3</spring-cloud.version>      </properties>        <dependencies>          <dependency>              <groupId>org.springframework.cloud</groupId>              <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-security</artifactId>              <scope>compile</scope>          </dependency>            <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-actuator</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.cloud</groupId>              <artifactId>spring-cloud-starter-sleuth</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-test</artifactId>              <scope>test</scope>              <exclusions>                  <exclusion>                      <groupId>org.junit.vintage</groupId>                      <artifactId>junit-vintage-engine</artifactId>                  </exclusion>              </exclusions>          </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>

   1.2  安全配置

package com.devin.eurekaserver.config;    import org.springframework.security.config.annotation.web.builders.HttpSecurity;  import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;  import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;    @EnableWebSecurity  public class WebSecurityConfig extends WebSecurityConfigurerAdapter {        @Override      protected void configure(HttpSecurity http) throws Exception {          //關閉csrf          super.configure(http);          //開啟認證          http.csrf().disable();      }  }  

 1.3 啟動類

    

package com.devin.eurekaserver;    import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconfigure.SpringBootApplication;  import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;    @EnableEurekaServer  @SpringBootApplication  public class EurekaServerApplication {        public static void main(String[] args) {          SpringApplication.run(EurekaServerApplication.class, args);      }    }  

  1.4  eureka-server application.yml 配置

      啟動埠為 7001

server:    port: 7001 #啟動埠  spring:    #應用名稱    application:      name: eureka-server    #安全配置    security:      basic:        enabled: true      user:        name: dev        password: 123456    #eureka配置  eureka:    server:      #設置掃描失效服務的間隔時間      eviction-interval-timer-in-ms: 20000      enable-self-preservation: true    instance:      hostname: localhost      leaseRenewalIntervalInSeconds: 10      health-check-url-path: /actuator/health    client:      register-with-eureka: false  #false:不作為一個客戶端註冊到註冊中心      fetch-registry: false        #為true時,可以啟動,但報異常:Cannot execute request on any known server      service-url:        defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/    # health endpoint是否必須顯示全部細節。默認情況下, /actuator/health 是公開的,並且不顯示細節。  # 設置actuator開關  management:    security:      enabled: false    endpoints:      web:        exposure:          include: "*"    endpoint:      health:        show-details: ALWAYS

 

 2. 配置中心config

   2.1  pom.xml 完整配置

   主要添加了 config-server(配置中心) ,mq ,actuator(spring bus配置中心刷新), eureka-client 的依賴

   ps: 搭建時在使用idea自帶的版本時,在用到配置刷新時會報mq的異常,所以這裡更改了spirngboot和spirng cloud的版本,具體看配置文件

    

<?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 https://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.2.RELEASE</version>          <relativePath/> <!-- lookup parent from repository -->      </parent>      <groupId>com.devin</groupId>      <artifactId>eureka-config</artifactId>      <version>0.0.1-SNAPSHOT</version>      <name>eureka-config</name>      <description>Demo project for Spring Boot</description>        <properties>          <java.version>1.8</java.version>          <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>      </properties>        <dependencies>            <dependency>              <groupId>org.springframework.cloud</groupId>              <artifactId>spring-cloud-config-server</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.cloud</groupId>              <artifactId>spring-cloud-starter-netflix-eureka-client</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-sleuth</artifactId>          </dependency>            <!-- springcloud-bus依賴實現配置自動更新,rabbitmq -->          <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>              <exclusions>                  <exclusion>                      <groupId>org.junit.vintage</groupId>                      <artifactId>junit-vintage-engine</artifactId>                  </exclusion>              </exclusions>          </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>

   2.2  啟動類

   @EnableConfigServer 對config配置中心的支援

   @EnableEurekaClient 將配置中心也作為一個eureka-client在註冊中心進行註冊

   

package com.devin.eurekaconfig;    import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconfigure.SpringBootApplication;  import org.springframework.cloud.config.server.EnableConfigServer;  import org.springframework.cloud.netflix.eureka.EnableEurekaClient;      @EnableConfigServer  @EnableEurekaClient  @SpringBootApplication  public class EurekaConfigApplication {        public static void main(String[] args) {          SpringApplication.run(EurekaConfigApplication.class, args);      }    }  

  

 2.3  config配置中心的配置文件

   我們這裡採用了多profile的配置,分別對應dev和test環境

 

    2.3.1 bootstrap.yml

 

      主要配置了連接git倉庫的地址,這裡我們查找的路徑按項目進行劃分,使用了{application}佔位,當客戶端的服務名為eureka-clent時,將在git地址的eureka-client文件夾下進行配置查找並使用

 

server:    port: 7009    spring:    profiles:      active: dev    #應用名稱    application:      name: eureka-config    cloud:      config:        server:          git:            uri: https://github.com/devinzhang0209/eureka-config-resp1.git  #          username: devinzhang0209  #          password: yourgithubpassword            search-paths: /{application}        label: master    # health endpoint是否必須顯示全部細節。默認情況下, /actuator/health 是公開的,並且不顯示細節。  management:    endpoints:      web:        exposure:          include: "*"    endpoint:      health:        show-details: ALWAYS

 

    2.3.2 測試環境功能 bootstrap-dev.yml

    主要配置了向eureka-server 進行註冊,以及mq的配置用於配置的刷新

#配置config服務的帳號密碼  spring:    security:      user:        name: dev-config        password: 123456    rabbitmq:      host: localhost      port: 5672      username: guest      password: guest    #註冊中心配置  eureka:    auth:      user: dev      password: 123456    client:      service-url:        defaultZone: http://${eureka.auth.user}:${eureka.auth.password}@localhost:7001/eureka/    instance:      #使用IP進行註冊      prefer-ip-address: true      #配置實例的註冊ID      instance-id: ${spring.cloud.client.ip-address}:${server.port}      #心跳時間,即服務續約間隔時間(預設為30s)      lease-renewal-interval-in-seconds: 5      #發獃時間,即服務續約到期時間(預設為90s)      lease-expiration-duration-in-seconds: 10      health-check-url-path: /actuator/health

  

  

    2.3.3 測試環境功能 bootstrap-test.yml

     這裡的配置和dev環境一樣,主要是為了測試test環境去讀取git倉庫中test對應的配置資訊

     

#配置config服務的帳號密碼  spring:    security:      user:        name: dev-config-test        password: test123456    #註冊中心配置  eureka:    auth:      user: dev-test      password: test123456    client:      service-url:        defaultZone: http://${eureka.auth.user}:${eureka.auth.password}@192.168.0.12:7001/eureka/    instance:      #使用IP進行註冊      prefer-ip-address: true      #配置實例的註冊ID      instance-id: ${spring.cloud.client.ip-address}:${server.port}      #心跳時間,即服務續約間隔時間(預設為30s)      lease-renewal-interval-in-seconds: 5      #發獃時間,即服務續約到期時間(預設為90s)      lease-expiration-duration-in-seconds: 10      health-check-url-path: /actuator/health

 

  3. git倉庫 eureka-config-resp1

   git倉庫中主要存儲了不同eureka-client客戶端的不同環境對應的配置文件, 結構如下:

    

   

 

  

    git的地址是 https://github.com/devinzhang0209/eureka-config-resp1.git 這裡我設置的是一個公共的倉庫

   

    下面我們展示eureka-clien的配置

      3.1  application.yml 

       

spring:    application:      name: eureka-client

     3.2  application-dev.yml

   

server:    port: 7003  msg: this msg is response by port 7003

 

     3.3 application-test.yml

  

server:    port: 7004  msg: this msg is response by port 7004

 

4. eureka-client 

   4.1 pom.xml

   

<?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 https://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.2.RELEASE</version>          <relativePath/> <!-- lookup parent from repository -->      </parent>      <groupId>com.devin</groupId>      <artifactId>eureka-client</artifactId>      <version>0.0.1-SNAPSHOT</version>      <name>eureka-client</name>      <description>Demo project for Spring Boot</description>        <properties>          <java.version>1.8</java.version>          <!--<spring-cloud.version>Hoxton.SR3</spring-cloud.version>-->          <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>      </properties>        <dependencies>            <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>              <version>1.4.1.RELEASE</version>          </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-web</artifactId>              <version>2.1.8.RELEASE</version>          </dependency>              <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-actuator</artifactId>          </dependency>              <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-test</artifactId>              <scope>test</scope>              <exclusions>                  <exclusion>                      <groupId>org.junit.vintage</groupId>                      <artifactId>junit-vintage-engine</artifactId>                  </exclusion>              </exclusions>          </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>

  4.2  啟動類

    

package com.devin.eurekaclient;    import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconfigure.SpringBootApplication;  import org.springframework.cloud.netflix.eureka.EnableEurekaClient;    @EnableEurekaClient  @SpringBootApplication  public class EurekaClientApplication {        public static void main(String[] args) {          SpringApplication.run(EurekaClientApplication.class, args);      }    }  

  

4.3  controller 測試類

  其中 @RefreshScope,用於後續spring config bus刷新配置文件

 

package com.devin.eurekaclient.controller;    import org.springframework.beans.factory.annotation.Value;  import org.springframework.cloud.context.config.annotation.RefreshScope;  import org.springframework.web.bind.annotation.GetMapping;  import org.springframework.web.bind.annotation.RestController;    /**   * @author Devin Zhang   * @className HelloController   * @description TODO   * @date 2020/4/2 9:50   */  @RefreshScope  @RestController  public class HelloController {      @Value("${server.port}")      private Integer port;        @Value("${msg}")      private String msg;        @GetMapping("/getMSG")      public String getMsg() {          return msg + " ,response by port:" + port;      }  }  

  

4.4  eureka-client的本地配置文件

   4.4.1 bootstrap.yml

     

spring:    profiles:      active: dev    #應用名稱    application:      name: eureka-client  # health endpoint是否必須顯示全部細節。默認情況下, /actuator/health 是公開的,並且不顯示細節。  management:    endpoints:      web:        exposure:          include: "*"    endpoint:      health:        show-details: ALWAYS

   4.4.2  bootstrap-dev.yml

       

#註冊中心配置  eureka:    auth:      user: dev      password: 123456    client:      service-url:        defaultZone: http://${eureka.auth.user}:${eureka.auth.password}@localhost:7001/eureka/    instance:      #使用IP進行註冊      prefer-ip-address: true      #配置實例的註冊ID      instance-id: ${spring.cloud.client.ip-address}:${server.port}      #心跳時間,即服務續約間隔時間(預設為30s)      lease-renewal-interval-in-seconds: 5      #發獃時間,即服務續約到期時間(預設為90s)      lease-expiration-duration-in-seconds: 10      health-check-url-path: /actuator/health    spring:    cloud:      #config服務配置      config:        username: dev-config        password: 123456        fail-fast: false        #重試間隔時間        retry:          initial-interval: 3000        #從註冊中心獲取配置服務,以及配置服務名稱        discovery:          enabled: true          service-id: eureka-config    rabbitmq:      host: localhost      port: 5672      username: guest      password: guest

  

    4.4.3  bootstrap-test.yml  

     

#註冊中心配置  eureka:    auth:      user: dev      password: 123456    client:      service-url:        defaultZone: http://${eureka.auth.user}:${eureka.auth.password}@localhost:7001/eureka/    instance:      #使用IP進行註冊      prefer-ip-address: true      #配置實例的註冊ID      instance-id: ${spring.cloud.client.ip-address}:${server.port}      #心跳時間,即服務續約間隔時間(預設為30s)      lease-renewal-interval-in-seconds: 5      #發獃時間,即服務續約到期時間(預設為90s)      lease-expiration-duration-in-seconds: 10      health-check-url-path: /actuator/health    spring:    cloud:      #config服務配置      config:        username: dev-config        password: 123456        fail-fast: false        #重試間隔時間        retry:          initial-interval: 3000        #從註冊中心獲取配置服務,以及配置服務名稱        discovery:          enabled: true          service-id: eureka-config    rabbitmq:      host: localhost      port: 5672      username: guest      password: guest

 

5. eureka-client2 

 eureka-client2 和 eureka-client 完全一樣只是實例的名稱不一樣,方便我們驗證多個client在配置中心註冊 ,此處程式碼就不在展示

 

7. 消息隊列RabbitMQ

   配置中心刷新時需要用到消息隊列

   7.1 安裝RabbitMQ  

     本文直接在windows上驗證,需要安裝如下軟體:

     Erlang  otp_win64_22.3.exe

     RabbitMQ rabbitmq-server-3.8.3.exe

   7.2 配置環境變數

     安裝完成後需要如下環境變數

     ERLANG_HOME=D:Program Fileserl10.7

     RABBITQM_SERVER=D:Program FilesRabbitMQ Serverrabbitmq_server-3.8.3

     path=%Path%;%ERLANG_HOME%bin;%RABBITQM_SERVER%sbin;

   

    7.3 啟動mq的服務

       

 

 

   7.4 開啟RabbitMQ管理服務端

     rabbitmq-plugins enable rabbitmq_management

     

    開啟後訪問的默認地址: http://localhost:15672/  默認帳號密碼 guest/guest

 

8 驗證配置中心

 

分別啟動

eureka-server 

eureka-config

eureka-client

eureka-client2 

 

啟動 eureka-client 和eureka-clent2 從啟動日誌中可以看到程式已經去配置中心7009讀取配置並從github上讀取了配置文件並使用

 

 

分別訪問 

http://localhost:7003/getMSG

http://localhost:7005/getMSG

可以看到euerka-client 和 eureka-client2 已經讀取了啟動埠,Controller也通過@Value讀取了git中的配置資訊

 

 

 

 

 9. Spring Cloud Bus 刷新配置 

   刷新配置我們需要注意如下幾點

   1. 在使用刷新配置時,需要去掉eureka-config 和eueka-client 中的安全驗證 ,直接在pom文件中去掉如下依賴即可

     

    <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-security</artifactId>              <scope>compile</scope>          </dependency>

   2. 在eureka-config 和eueka-client 的yml配置文件中添加RabbitMQ的配置

     

#配置config服務的帳號密碼  spring:    security:      user:        name: dev-config        password: 123456    rabbitmq:      host: localhost      port: 5672      username: guest      password: guest

  3. 在客戶端所有用到讀取配置文件的類上加上 @RefreshScope

  4. 刷新配置

    刷新配置可以訪問eureka-config也可以訪問任何一個eureka-client的服務進行刷新,如下刷新請求只能通過post請求去調用

    通過eureka-config 去刷新   http://localhost:7009/actuator/bus-refresh

    通過eureka-client 去刷新   http://localhost:7003/actuator/bus-refresh

    刷新後我們再後台log中可以看到,客戶端已經去github上重新讀取了最新的配置

   

 

 

   

 

 

再次訪問客戶端,可以看到客戶端已經讀取到了最新的配置

 

http://localhost:7003/getMSG

http://localhost:7005/getMSG

 

 

 

 

 至此,spring cloud config配置中心搭建完畢