天天看點

SpringCloud(九)Spring Cloud Config 分布式配置中心SpringCloud(九)Spring Cloud Config 分布式配置中心

SpringCloud(九)Spring Cloud Config 分布式配置中心

分布式配置中心應用場景

往往,我們使用配置檔案管理一些配置資訊,比如application.properties

單體應用架構,配置資訊的管理、維護并不會顯得特别麻煩,手動操作就可以,因為就一個工程;

微服務架構,因為我們的分布式叢集環境中可能有很多個微服務,我們不可能一個一個去修改配置然後重新開機生效,在一定場景下我們還需要在運作期間動态調整配置資訊,比如:根據各個微服務的負載情況,動态調整資料源連接配接池大小,我們希望配置内容發生變化的時候,微服務可以自動更新。

場景總結如下:

1)集中配置管理,一個微服務架構中可能有成百上千個微服務,是以集中配置管理是很重要的(一次修改、到處生效)

2)不同環境不同配置,比如資料源配置在不同環境(開發dev,測試test,生産prod)中是不同的

3)運作期間可動态調整。例如,可根據各個微服務的負載情況,動态調整資料源連接配接池大小等配置修改後可自動更新

4)如配置内容發生變化,微服務可以自動更新配置

那麼,我們就需要對配置檔案進行集中式管理,這也是分布式配置中心的作用。

Spring Cloud Config

Config簡介

Spring Cloud Config是一個分布式配置管理方案,包含了 Server端和 Client端兩個部分。

SpringCloud(九)Spring Cloud Config 分布式配置中心SpringCloud(九)Spring Cloud Config 分布式配置中心
  • Server 端:提供配置檔案的存儲、以接口的形式将配置檔案的内容提供出去,通過使用@EnableConfigServer注解在 Spring boot 應用中非常簡單的嵌入
  • Client 端:通過接口擷取配置資料并初始化自己的應用

Config分布式配置應用

說明:Config Server是集中式的配置服務,用于集中管理應用程式各個環境下的配置。 預設使用Git存儲配置檔案内容,也可以SVN。

比如,我們要對“靜态化微服務或者商品微服務”的application.yml進行管理(區分開發環境(dev)、測試環境(test)、生産環境(prod))

1)登入GitHub,建立項目szx-config

2)上傳yml配置檔案,命名規則如下:

{application}-{profile}.yml 或者 {application}-{profile}.properties

其中,application為應用名稱,profile指的是環境(用于區分開發環境,測試環境、生産環境等)

示例:szx-service-page-dev.yml、szx-service-page-test.yml、szx-service-page-prod.yml

3)建構Config Server統一配置中心

建立SpringBoot工程,引入依賴坐标(需要注冊自己到Eureka)

<dependencies>
    <!--eureka client 用戶端依賴引入-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--config配置中心服務端-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
</dependencies>
           

配置啟動類,使用注解@EnableConfigServer開啟配置中心伺服器功能

@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer     //開啟配置伺服器功能
public class ConfigApplication {

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

}
           

application.yml配置

#配置端口
server:
  port: 9400

#配置Eurake,将網關注冊到Eureka
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:9202/eureka/,http://127.0.0.1:9201/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@

#配置config
spring:
  application:
    name: szx-service-config
  #配置GitHub
  cloud:
    config:
      server:
        #配置git服務位址
        git:
          uri: https://gitee.com/lemonStar/szx-config.git     #配置GIT位址
          username: #GIT使用者名
          password: #GIT密碼
          search-paths:
            - szx-config
      #指定分支
      label: master
           

測試:http://127.0.0.1:9400/master/application_dev.yml

  • master:分支名稱
  • application-dev.yml:檔案名稱

4)建構Client用戶端(在已有頁面靜态化微服務基礎上)

案例實作:在szx-service-page微服務中動态擷取config server的配置資訊

已有工程中添加依賴坐标

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

application.properties修改為bootstrap.properties配置檔案

bootstrap.yml是系統級别的,優先級比application.yml高,應用啟動時會檢查這個配置檔案,在這個配置檔案中指定配置中心的服務位址,會自動拉取所有應用配置并且啟用。

(主要是把與統一配置中心連接配接的配置資訊放到bootstrap.yml)

注意:需要統一讀取的配置資訊,從配置中心擷取

bootstrap.properties(部分)

#配置springcloud config(分布式配置中心的配置)資訊
spring.cloud.config.name=application
spring.cloud.config.profile=dev
#分支名稱
spring.cloud.config.label=master
#config server位址
spring.cloud.config.uri=http://127.0.0.1:9400
           
@RestController
@RequestMapping("/config")
public class ConfigClientController {

    @Value("${mysql.user}")
    private String user;

    @Value("${person.name}")
    private String name;

    @GetMapping("/getConfigInfo")
    public String getConfigInfo(){
        return user + name;
    }

}
           

Config配置手動重新整理

不用重新開機微服務,隻需要手動的做一些其他的操作(通路一個位址/refresh)重新整理,之後再通路即可

此時,用戶端取到了配置中心的值,但當我們修改GitHub上面的值時,服務端(Config Server)能實時擷取最新的值,但用戶端(Config Client)讀的是緩存,無法實時擷取最新值。Spring Cloud已 經為我們解決了這個問題,那就是用戶端使用post去觸發refresh,擷取最新資料。

1)Client用戶端添加依賴springboot-starter-actuator(已添加)

2)Client用戶端bootstrap.yml中添加配置(暴露通信端點)

#springboot中暴露健康檢查等斷點接口
management.endpoints.web.exposure.include=*
#或者
management.endpoints.web.exposure.include=refresh
           

3)Client用戶端使用到配置資訊的類上添加@RefreshScope

@RestController
@RequestMapping("/config")
@RefreshScope       //手動重新整理
public class ConfigClientController {

    @Value("${mysql.user}")
    private String user;

    @Value("${person.name}")
    private String name;

    @GetMapping("/getConfigInfo")
    public String getConfigInfo(){
        return user + name;
    }

}
           

4)手動向Client用戶端發起POST請求,http://localhost:9100/actuator/refresh,重新整理配置資訊

注意:手動重新整理方式避免了服務重新開機

思考:可否使用廣播機制,一次通知,處處生效,友善大範圍配置自動重新整理?

Config配置自動更新

實作一次通知,處處生效

在微服務架構中,我們可以結合消息總線(Bus)實作分布式配置的自動更新(Spring Cloud Config + Spring Cloud Bus)

消息總線Bus

所謂消息總線Bus,即我們經常會使用MQ消息代理建構一個共用的Topic,通過這個Topic連接配接各個微服務執行個體,MQ廣播的消息會被所有在注冊中心的微服務執行個體監聽和消費。換言之就是通過一個主題連接配接各個微服務,打通脈絡。

Spring Cloud Bus(基于MQ的,支援RabbitMq/Kafka) 是Spring Cloud中的消息總線方案,Spring Cloud Config + Spring Cloud Bus 結合可以實作配置資訊的自動更新。

SpringCloud(九)Spring Cloud Config 分布式配置中心SpringCloud(九)Spring Cloud Config 分布式配置中心

Spring Cloud Config + Spring Cloud Bus 實作自動重新整理

MQ消息代理,我們還選擇使用RabbitMQ,ConfigServer和ConfigClient都添加都消息總線的支援以及與RabbitMq的連接配接資訊

1)Config Server服務端和用戶端添加消息總線支援

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
           

2)Config Server和用戶端添加配置

spring:
  rabbitmq:
    host: IP
    port: 5672
    username: guest
    password: guest
           

3)Config Server微服務暴露端口

#springboot中暴露健康檢查等斷點接口
management.endpoints.web.exposure.include=*
#或者
management.endpoints.web.exposure.include=bus-refresh
           

4)重新開機各個服務,更改配置之後,向配置中心服務端發送post請求,各個用戶端配置即可自動重新整理 http://127.0.0.1:9400/actuator/bus-refresh

5)Config Client測試 http://localhost:9100/config/remote

在廣播模式下實作了一次請求,處處更新,如果我隻想定向更新呢?

在發起重新整理請求的時候 http://localhost:9006/actuator/bus-refresh/lagou-service-page:9100

即為最後面跟上要定向重新整理的執行個體的 **服務名:端口号 **即可