天天看點

【Spring Cloud總結】33.編寫Config Client

接上篇《32.編寫Config Server》  Spring Cloud版本為Finchley.SR2版

上一篇我們搭建了一個私有遠端倉庫,并編寫了Spring Cloud Config的Server服務端,連接配接遠端倉庫并成功提供了配置服務端點。本篇我們來編寫Spring Cloud Config的Client用戶端。

本部分官方文檔:https://cloud.spring.io/spring-cloud-static/Finchley.SR4/single/spring-cloud.html#_client_side_usage_2

注:好像Finchley.SR2的文檔已經挂了,最新的是Finchley.SR4的文檔。

我們依舊來回顧Spring Cloud Config的架構圖:

【Spring Cloud總結】33.編寫Config Client

上一篇我們編寫的Config Server服務端可以從後端存儲中(上圖為Git)拉取配置參數、屬性,然後對外提供擷取相應環境(dev開發、stage預釋出、prod生産)配置的Restful服務。此時我們的Config Client用戶端就可以通過Config Server提供的服務擷取相關配置。

下面我們就來動手編寫一個Config Client用戶端,對接我們上一篇編寫的Config Server服務端。

一、建立Config Client用戶端工程

在工作空間中建立一個名為“microserver-config-client”的Maven工程:

【Spring Cloud總結】33.編寫Config Client
【Spring Cloud總結】33.編寫Config Client

然後在POM檔案中引入Spring Cloud的父工程、config-client的依賴,因為我們這個用戶端需要使用SpringMVC,是以這裡添加了web的依賴:

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <artifactId>microserver-config-client</artifactId>
  <name>microserver-config-client</name>
  
  <parent>
        <groupId>com.microserver.cloud</groupId>
        <artifactId>microserver-spring-cloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
  
  <dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
  
</project>
           

注意,這裡為了便于版本統一管理,該工程的parent父工程和我們User、Movie工程一樣,均依賴于microserver-spring-cloud工程(此父工程統一引入了spring-cloud-dependencies的Finchley.SR2版,這個在前面的章節已經講過)。

父工程pom.xml的modules中别忘記加入這個新工程(microserver-config-client):

<modules>
    <module>microserver-provider-user</module>
    <module>microserver-consumer-movie</module>
    <module>microserver-discovery-eureka</module>
    <module>microserver-discovery-eureka-high-availability</module>
    <module>microserver-hystrix-dashboard</module>
    <module>microserver-hystrix-dashboard-turbine</module>
    <module>microserver-getaway-zuul</module>
    <module>microserver-file-upload</module>
    <module>microserver-sidecar</module>
    <module>microserver-config-server</module>
    <module>microserver-config-client</module>
</modules>
           

然後我們建立SpringBoot啟動類:

package com.microserver.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConfigClientApplication {

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

}
           

然後在resource檔案夾下建立application.yml,配置一下端口,以及拉取配置的後端存儲的uri路徑、應用名,以及Config Server的服務位址,以及需要從Config Server擷取的配置版本資訊:

server:
  port: 8091
spring:
  application:
    name: microserver-config-client
  cloud:
    config:
      uri: http://localhost:8090
      profile: dev
      label: master  #如果ConfigServer的後端存儲是Git,預設就為master
           

然後我們建立一個Controller來編寫一個服務,通過該服務擷取Config Server的配置:

package com.microserver.cloud;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConfigClientController {
    
    @Value("${type}")
    private String profileType;
    
    @GetMapping("/profileType")
    private String getProfileType() {
        return this.profileType;
    }
} 
           

注:這裡的${type},就是之前我們放在倉庫裡的預設dev配置檔案的參數:

【Spring Cloud總結】33.編寫Config Client

此時我們的用戶端算是搭建完畢了,這樣就能直接擷取資訊了嗎?我們來試試。

二、Config Client的加載問題

先後啟動microserver-config-server和microserver-config-client工程,我們可以看到microserver-config-client工程的控制台報錯了:

【Spring Cloud總結】33.編寫Config Client

下面的異常資訊就是加載不了“${type}”的值,而具體原因是上面的“Fetching config from server at : http://localhost:8888”,但是我們的spring.cloud.config.uri不是配置的“http://localhost:8090”嗎?我們來探讨一下原因。

首先我們需要了解一下Bootstrap Application Context,叫“啟動上下文”(官方文檔解釋:https://cloud.spring.io/spring-cloud-static/Finchley.SR4/single/spring-cloud.html#_the_bootstrap_application_context),它是用來加載遠端的ConfigServer的配置。啟動的時候内置的bootstrap.yml配置檔案,然後擷取Config Server的配置,去連接配接Config Server,然後再去加載application.yml檔案。而由于預設的bootstrap.yml配置檔案中的spring.cloud.config.uri是“http://localhost:8888”,是以我們加載不出來。

此時我們在resource下建立一個名為bootstrap.yml的配置檔案,在裡面設定spring.cloud.config.uri:

spring:
  cloud:
    config:
      uri: http://localhost:8090
      profile: dev
      label: master  #如果ConfigServer的後端存儲是Git,預設就為master
           

然後把原來在application.yml中的spring.cloud.config.uri配置删除:

server:
  port: 8091
spring:
  application:
    name: microserver-config-client
           

工程檔案結構:

【Spring Cloud總結】33.編寫Config Client

然後我們重新開機工程,發現控制台不再報錯,然後我們通路"/profileType"服務,發現可以拿到資料:

【Spring Cloud總結】33.編寫Config Client

我們在gitee倉庫中存儲的application-dev.yml中的内容即是:

type: dev

但這其實隻是擷取到了預設的dev配置檔案,要知道Config Server擷取參數的機制如下:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
           

這裡的“application”字首,即是我們的應用名“spring.application.name”,我們在本地倉庫建立一個“microserver-config-client-dev.yml”檔案,内容為“type: client-dev”:

【Spring Cloud總結】33.編寫Config Client

然後上傳到遠端倉庫:

【Spring Cloud總結】33.編寫Config Client
【Spring Cloud總結】33.編寫Config Client
【Spring Cloud總結】33.編寫Config Client

此時重新開機服務,重新通路"/profileType"服務,發現可以拿到該應用名對應的配置檔案的資料:

【Spring Cloud總結】33.編寫Config Client

至此,我們的Config Client成功擷取到配置倉庫的對應資訊。我們不同的應用可以根據不同的applicationName去遠端倉庫擷取自己應用對應的配置内容。

二、相關問題

1、本地配置和遠端配置沖突問題

上面我們在Controller中使用@Value("${type}")注解注入了type參數,這個type參數是遠端倉庫中的參數,那麼此時如果我們在application.yml配置檔案中,加一個本地的參數type會怎樣呢:

server:
  port: 8091
spring:
  application:
    name: microserver-config-client
    
type: abcd
           

我們重新開機microserver-config-client工程,通路"/profileType"服務,看一下type的值:

【Spring Cloud總結】33.編寫Config Client

發現還是以遠端的type值為主,并沒有被本地的同名參數值(abcd)覆寫。

這個機制也很好解釋,因為系統先加載bootstrap.yml配置檔案擷取了配置值,然後注入到Controller的參數中,而我們的Controller加載完畢之後,是一個單例狀态,注入的資料已經在這個單例類中,不會再次覆寫。後面我們再加載application.yml時,type已經被注入Controller中了。

2、spring.application.name與遠端倉庫檔案的關系

如果應用沒有設定spring.application.name應用名,或倉庫沒有找到對應的應用名的配置檔案,則隻會取到application-*.yml這種預設的配置檔案,是以要確定工程的spring.application.name已配置,并且在遠端倉庫中托管有這種應用名字首的配置檔案。

參考:《51CTO學院Spring Cloud進階視訊》

轉載請注明出處:https://blog.csdn.net/acmman/article/details/104718599

繼續閱讀