Spring Cloud 之 Config與動態路由.

1、簡介

 Spring Cloud Confg 是用來爲分佈式系統中的基礎設施和微服務應用提供集中化的外部配置支持,它分爲服務端與客戶端兩個部分。其中服務端也稱爲分佈式配置中心,它是一個獨立的微服務應用,用來鏈接配置倉庫併爲客戶端提供獲取配置信息、加密/解密信息等訪問接口;而客戶端則是微服務架構中的各個微服務應用或基礎設施,它們經過指定的配置中心來管理應用資源與業務相關的配置內容,並在啓動的時候從配置中心獲取和加載配置信息。html

2、Spring Config Server

搭建一個 Config Server,首先須要一個倉庫,做爲分佈式配置中心的存儲。這裏咱們選擇了 Github 做爲咱們的倉庫:https://github.com/JMCuixy/cloud-config-server/tree/master/config-repo
java

1. pom.xml

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

        <!--啓動 security 保護,不須要可不添加-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

2. application.yml

server:
  port: 7001

spring:
  application:
    name: cloud-config-server

  # 配置完成後可訪問的 url 以下,好比:http://localhost:7001/env/default
  # /{application}/{profile} [/{label}]
  # /{application}-{profile}.yml
  # /{label}/{application}-{profile}.yml
  # /{application}-{profile}.properties
  # /{label}/{application}-{profile}.properties
  cloud:
    config:
      # 爲配置中心提供安全保護
      username: user
      password: password
      server:
        git:
          # 倉庫地址
          uri: https://github.com/JMCuixy/cloud-config-server.git
          # 搜索路徑
          search-paths: config-repo
        # 訪問 http://localhost:7001/actuator/health 能夠獲取配置中心健康指標
        health:
          repositories:
            env:
              name: env
              profiles: default
              label: master
            env-dev:
              name: env-dev
              profiles: dev
              label: master
            env-test:
              name: env-test
              profiles: test
              label: master
            env-prod:
              name: env-prod
              profiles: prod
              label: master

  # 提供 security 保護
  security:
    user:
      name: user
      password: password

management:
  endpoint:
    health:
      enabled: true
      show-details: always

eureka:
  client:
    service-url:
      defaultZone: http://user:password@localhost:1111/eureka/

這裏我沒有配置 Github 的 username 和 password,用的是 SSH key 的方式。git

3. ConfigApplication.java

// 開啓 Spring Cloud Config 的 Server 功能
@EnableConfigServer
@EnableDiscoveryClient
@SpringBootApplication
public class ConfigApplication {

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

}

至此,一個 Spring Cloud Config Server 就搭建完成了。上面的配置中,咱們將 Config Server 註冊到 Eureka Server 中,看成整個系統服務的一部分,因此Config Client 只要利用 Eureka 的服務發現維持與 Config Server 通訊就能夠了。github

在Config Server 的文件系統中,每次客戶端請求獲取配置信息時,Confg Server 從 Git 倉庫中獲取最新配置到本地,而後在本地 Git 倉庫中讀取並返回。當遠程倉庫沒法獲取時,直接將本地內容返回。web

2、Spring Config Client

Spring Cloud Confg 的客戶端在啓動的時候,默認會從工程的 classpath 中加載配置信息並啓動應用。只有當咱們配置 spring.cloud.config.uri(或者spring.cloud.config.discovery) 的時候,客戶端應用纔會嘗試鏈接 Spring Cloud Confg 的服務端來獲取遠程配置信息並初始化 Spring 環境配置。同時,咱們必須將該參數配置在bootstrap.yml、環境變量或是其餘優先級高於應用 Jar 包內的配置信息中,才能正確加載到遠程配置。spring

1. pom.xml

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

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!-- 當鏈接 config-server 失敗的時候,可增長重試-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>

        <!--配置動態刷新-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

2. bootstrap.yml 和 application.yml

  • bootstrap.yml
spring:
  application:
    # 對應配置文件規則中的 {application} 部分
    name: env
  cloud:
    config:
      name: env
      # uri: http://localhost:7001
      discovery:
        enabled: true
        service-id: cloud-config-server
      # 環境變量  
      profile: default
      # 分支
      label: master
      # config Server 配置的安全信息
      username: user
      password: password
      # 快速失敗響應(當發現 config-server 鏈接失敗時,就不作鏈接的準備工做,直接返回失敗)
      fail-fast: true
      # 失敗重試
      retry:
        # 初始重試間隔時間,毫秒
        initial-interval: 1000
        # 下一間隔的乘數
        multiplier: 1.1
        # 最大間隔時間
        max-interval: 2000
        # 最多重試次數
        max-attempts: 6

bootstrap 配置會系統會優先加載,加載優先級比 application 高。bootstrap

  • application.yml
server:
  port: 7002

spring:
  application:
    name: cloud-config-client

eureka:
  client:
    service-url:
      defaultZone: http://user:password@localhost:1111/eureka/

management:
  endpoints:
    web:
      exposure:
        # 開啓指定端點
        # 配置刷新地址:POST http://127.0.0.1:7002/actuator/refresh
        include: 'refresh'

3. ConfigClientApplication.java

@EnableDiscoveryClient
@SpringBootApplication
public class ConfigClientApplication {

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

}

4. 應用

接下來瞅瞅客戶端要怎麼讀到服務器的配置項呢?安全

@RefreshScope
@RestController
public class ConfigClientAdmin {

    @Value("${from:default}")
    private String from;

    @Autowired
    private Environment environment;


    @RequestMapping("/from")
    public String from() {
        String fromEnv = environment.getProperty("from");
        return from + "_" + fromEnv;
    }
}

如上,咱們可使用 @Value 註解注入配置信息,或者使用 Environment Bean 來獲取配置項。服務器

須要注意的是,當服務端的配置項更新的時候,客戶端並不會同步得到更新,須要 Post 方法執行 "/actuator/refresh" 來刷新配置項。架構

@RefreshScope 註解使配置的內容動態化,當使用 http://127.0.0.1:7002/actuator/refresh 刷新配置的時候,會刷新帶有 @RefreshScope 的 Bean。

3、動態路由

上一篇文章 咱們嘗試用 Spring Cloud Zuul 搭建了網關服務,可是咱們發現路由信息都配置在 application.yml 中,這對網關的高可用是個不小的打擊,由於網關做爲系統流量的路口,總不能由於改個路由信息每天重啓網關吧?因此動態路由的實現,就變得火燒眉毛了,好在咱們如今有了 Spring Cloud Config。

首先,咱們將 Spring Cloud Zuul 的路由信息,配置在 Config Server 的 env.yml 中:

zuul:
  routes:
    client-1:
      # ?:匹配任意單個數量字符;*:匹配任意多個數量字符;**:匹配任意多個數量字符,支持多級目錄
      # 使用 url 的配置沒有線程隔離和斷路器的自我保護功能,不推薦使用
      path: /client-1/**
      url: http://localhost:2222/
      # 敏感頭信息設置爲空,表示不過濾敏感頭信息,容許敏感頭信息滲透到下游服務器
      sensitiveHeaders: ""
      customSensitiveHeaders: true
    client-2:
      path: /client-2/**
      serviceId: cloud-eureka-client
    # zuul.routes.<serviceid> = <path>
    cloud-eureka-client: /client-3/**
    client-4:
      path: /client-4/**
      # 請求轉發 —— 僅限轉發到本地接口
      url: forward:/local

  # Zuul 將對全部的服務都不自動建立路由規則
  ignored-services: "*"
  # 對某些 url 設置不通過路由選擇
  ignored-patterns: {"/**/world/**","/**/zuul/**"}
  # Spring Cloud Zuul在請求路由時,會過濾掉 HTTP 請求頭(Cookie、Set-Cookie、Authorization)信息中的一些敏感信息,
  sensitive-headers: {"Cookie", "Set-Cookie", "Authorization"}
  # 網關在進行路由轉發時爲請求設置 Host 頭信息(保持在路由轉發過程當中 host 頭信息不變)
  add-host-header: true
  # 請求轉發時加上 X-Forwarded-*頭域
  add-proxy-headers: true
  # 是否開啓重試,默認關閉
  retryable: true
  # 經過 /zuul 路徑訪問的請求會繞過 dispatcherServlet, 被 Zuu1Servlet 處理,主要用來應對處理大文件上傳的狀況。
  servlet-path: /zuul
  # 禁用某個過濾器 zuul.<SimpleClassName>.<filterTye>.disable=true
  TokenFilter:
    pre:
      disable: true

而後,咱們將網關服務註冊爲 Config Client(配置項與上面相似,就不贅述了),從 Config Server 獲取路由信息:

@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class DynamicRouteApplication {

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

    /**
     * 刷新地址:POST http://127.0.0.1:5006/actuator/refresh
     * 路由查看地址:GET http://127.0.0.1:5006/actuator/routes
     *
     * @return
     */
    @Bean
    @Primary
    //該註解來使 zuul 的配置內容動態化
    @RefreshScope
    @ConfigurationProperties(prefix = "zuul")
    public ZuulProperties zuulProperties() {
        return new ZuulProperties();
    }

}

這樣,就把咱們的路由信息交給 Config Server 去管理了~~

演示源代碼 :https://github.com/JMCuixy/spring-cloud-demo

內容參考:《Spring Cloud 微服務實戰》

相關文章
相關標籤/搜索