聊聊Spring Cloud Config


Spring Cloud Config

轉自:https://blog.csdn.net/fjnpysh/article/details/71307311

現今這個時候,微服務大行其道,互聯網應用遍地都是,隨便開發個什么應用首要考慮的都是要可伸縮,擴展性要好。當我們的后台服務一點點增多,各個服務的配置也越來越多,隨之而來的就是一個配置管理問題,各自管各自的開發時沒什么問題,到了線上之后管理就會很頭疼,到了要大規模更新就更煩了。我們的后台服務就是如此,各種語言開發的都有,在慢慢的迭代過程的我們發現配置中心是一個比較好的解決方案,作為 Spring 的擁躉我們自然就看中了 Spring Cloud Config。

一般服務器的應用都有以下幾種類型,
圖片

其中當屬業務部分最多也最繁雜。
當應用越來越龐大和復雜時,單機就肯定不能滿足需求了,然后就要考慮分布式了,接下可能會應用不同的語言來開發應用。

比如 nginx 毫無疑問的是用的最多的反向代理組件,使用 OpenResty 便要用到 lua,再比如前端要 seo ,一個解決辦法就是使用 nodejs,到了后端分布式,那就更繁多了,可能會需要把業務一個個拆分成不同的服務單獨運行...

圖片

然后就發現散落一地的配置文件:***properties***、***yml***、***json*** …

為了解決這個問題,我們采取了這么一種模式,通過 etcd 我們的項目就是這樣,來收集所有的配置,然后統一的寫到一個文件中去,任何應用都來訪問這一個文件來找到自己的配置並應用。
圖片

這很好的解決了配置散落的問題,可以集中管理了,但是又存在另一個問題,各種類型的配置在一個文件里看起來好亂,而且在初始化時必須要完成這個文件才能啟動應用。

所以下一個解決方案便想到用一個配置中心來解決問題。

圖片

Spring Cloud Config 項目

  • 提供 服務端 和 客戶端 支持
  • 集中式 管理分布式環境下的應用配置
  • 基於 Spring 環境,無縫 與 Spring 應用集成
  • 可用於 任何 語言開發的程序
  • 默認實現基於 git 倉庫,可以進行 版本管理
  • 可替換 自定義實現

Spring Cloud Config Server 作為配置中心服務端

  • 拉取配置時更新 git 倉庫副本,保證是最新結果
  • 支持數據結構豐富,yml, json, properties 等
  • 配合 eureke 可實現服務發現,配合 cloud bus 可實現配置推送更新
  • 配置存儲基於 git 倉庫,可進行版本管理
  • 簡單可靠,有豐富的配套方案

Spring Cloud Config Client 默認客戶端實現

  • SpringBoot 項目不需要改動任何代碼,加入一個啟動配置文件指明使用 ConfigServer 上哪個配置文件即可

簡單使用示例

新建一個 git 倉庫,添加一個配置文件。例如想要一個 billing的服務,性質是開發,運行環境是測試環境。

那么就新建一個 testing 的分支,然后提交一個 billing-dev.properties 的文件

devMode = true
spring.application.name = billing
spring.jdbc.host = localhost
spring.jdbc.port = 3306
spring.jdbc.user = root
spring.jdbc.password = 123qwe
loging.file = demo

 

然后新建一個標准 maven 項目

圖片

ConfigServer.java
@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServer.class, args);
    }
}

application.yml

 

server:
  port: 8888
spring:
  cloud:
    config:
      server:
        git:
          uri:https://git.coding.net/tiangao/demo-config-server.git
          clone-on-start: true

 

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-demo</artifactId>
        <groupId>xyz.stg.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>config-server</artifactId>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.1.RELEASE</version>
    </parent>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
            <version>1.2.1.RELEASE</version>
        </dependency>
    </dependencies>
</project>

 

 

好了,配置中心已經可以啟動了,配最簡單的可以用瀏覽器來訪問。

圖片

想要 json 格式的怎么辦呢?
圖片

還有 yml, properties
圖片

圖片

OK, 就是這樣簡單。不過直接就能通過 url 得到,是不是有點不安全,這也不難,加上依賴。
java <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency>

然后在 application.yml 配置用戶名和密碼,user 便是用戶名。

 

security:
  user:
    password: db1ab002-1fba-476d-a421-22113355

再訪問就能看到如下的效果

圖片

這是 ConfigSever 默認實現的基本的 HttpBasic 的認證。

服務端好了現在來看看 SpringBoot 客戶端
只需要添加一個啟動配置文件:

java cloud: config: uri: http://127.0.0.1:8888
profile: dev label: testing name: billing password: db1ab002-1fba-476d-a421-22113355 username: user

當啟動時看到下面標示的內容是即表示加載成功。

圖片

簡單示例就這樣,下面便是 Config 的使用示意圖。
圖片

吶,就是這樣,所有的配置都通過倉庫來管理,應用啟動時訪問配置中心能拿到自己的配置就OK,再接下來就是各自的事情了。

倉庫也不僅僅只能用 git, 還有 svn 和本地目錄可以選擇

  • svn://\${user.home}/config-repo
  • file://${user.home}/config-repo

從簡單的示例里可以看出,我們只要提交一種格式的配置文件,通過不同的方式訪問即可得到不同格式的配置文件,這在ConfigServer里是如何實現的呢?

先看一共有多少種訪問方式

  • /{name}/{profiles:.*[^-].*}
  • /{name}/{profiles}/{label:.*}
  • /{name}-{profiles}.properties
  • /{label}/{name}
  • /{profiles}.properties
  • /{name}-{profiles}.json
  • /{label}/{name}-{profiles}.json

然后就能發現有這么一個類,里面有各種資源類型的轉換操作。EnvironmentController 的所有方法如下所示:

圖片

原來內部只存在一種資源抽象,所有的資源對象都是由這種類型轉換而來。
圖片

一個應用的配置只需要應用名、屬性和標簽就可以定位到。嗯,原來這么簡單,那 EnvironmentReposiroty 又是哪里實現呢?
圖片

findOne 方式在 AbstractScmEnvironmentRepository 中可以找到。

java @Override public synchronized Environment
findOne(String application, String profile, String label) { NativeEnvironmentRepository delegate = new NativeEnvironmentRepository( getEnvironment()); Locations locations
= getLocations(application, profile, label); delegate.setSearchLocations(locations.getLocations()); Environment result = delegate.findOne(application, profile, "");
result.setVersion(locations.getVersion()); result.setLabel(label); return this.cleaner.clean(result, getWorki

這其中又由 SearcPathLocator 接口的 getLocations() 來實際加載內容,這個方法就由具體的實現類來完成。

 

Spring Cloud Config Server 內部除了 JGitEnvironmentRepository 實現外還有另外三種實現。

  • SvnKitEnvironmentRepository
  • NativeEnvironmentRepository
  • MultipleJGitEnvironmentRepository

見名知其意,分別是 svn 本地目錄以及多 git 倉庫的實現。

來到客戶端這邊,SpringBoot

項目只需要加載依賴就可以使用到遠程配置,現有項目遷移過去也不用改動任何代碼,感覺好神奇。
達到這樣的效果依賴於 springMVC 的抽象以及 springboot 的自動配置類加載。
```java
@Configuration
public class ConfigClientAutoConfiguration {

@Bean
public ConfigClientProperties configClientProperties(
       Environment environment,
       ApplicationContext context) {...}
...
@Bean
public ConfigServerHealthIndicator configServerHealthIndicator(
       ConfigServicePropertySourceLocator locator,
       ConfigClientHealthProperties properties, Environment environment) {
    return new ConfigServerHealthIndicator(locator, environment, properties);
}

**ConfigClientAutoConfiguration** 這個是 ConfigClient 的自動配置類,加載時觸發新建一個 ConfigServicePropertySourceLocator 的 bean, 

java
@Order (0)
public class ConfigServicePropertySourceLocator
implements PropertySourceLocator {

private RestTemplate restTemplate;
private ConfigClientProperties defaultProperties;
...
@Override
@Retryable(interceptor = "configServerRetryInterceptor")
public org.springframework.core.env.PropertySource<?> locate(
       org.springframework.core.env.Environment environment) {
    ...
       // Try all the labels until one works
       for (String label : labels) {
         Environment result = getRemoteEnvironment(restTemplate,
              properties, label.trim(), state);
              ...

 

}
```

然后在 ApplicationContextInitializer 的 initialize 方法中被調用 locate 方法從 ConfigServer 拉取配置文件,注入到 ConfigurableEnvironment 中,

@Configuration
@EnableConfigurationProperties(PropertySourceBootstrapProperties.class)
public class PropertySourceBootstrapConfiguration implements
        ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
    ...
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ...
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        for (PropertySourceLocator locator : this.propertySourceLocators) {
            PropertySource<?> source = null;
            source = locator.locate(environment);
            if (source == null) {
                continue;
            }
            ...
        }
        ...
    }
}

 

  1. 接着才是應用的初始化過程。

從這個過程可以看到,其他任何應用需要使用 ConfigServer 時只需要在應用初始化之前通過 http 拉取到配置文件即可。

了解了大致原理,便可以看到集中式管理的優點。

圖片

    • 沒有記憶負擔:大家都使用一個倉庫保存所有配置文件,方便查看。

    • 降低沖突溝通成本:開發新功能是凡是有配置變動均向倉庫的提交,在合並后其他人碰到配置問題時也不用到處找人問,看看倉庫歷史就知道什么發生了變化。

    • 方便測試:測試環境下,測試人員也不用老是問開發環境配置的問題了,所有配置一目了然,更改配置也有記錄,有問題向開發反饋也能幫助快速定位問題范圍。

    • 方便管理: 在模擬環境和生產環境下,通過分支保護和權限管理管理線上配置文件,由運維人員來管理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM