【前面的話】本文的某些知識依賴我的微服務系列文章,如果沒有看過可以先移步去看一下,在前面的應用當中,我們所有的配置都是寫在yaml組態檔當中的,這樣就會造成幾個問題:安全、統一管理等等,而SpringCloud也是考慮到這一點,給出的方案就是Spring Cloud Config,
壹、Config的簡介
Spring Cloud Config是Spring Cloud團隊創建的一個全新專案,用來為分布式系統中的基礎設施和微服務應用提供集中化的外部配置支持,它分為服務端與客戶端兩個部分,其中服務端也稱為分布式配置中心,它是一個獨立的微服務應用,用來連接配置倉庫并為客戶端提供獲取配置資訊、加密/解密資訊等訪問介面;而客戶端則是微服務架構中的各個微服務應用或基礎設施,它們通過指定的配置中心來管理應用資源與業務相關的配置內容,并在啟動的時候從配置中心獲取和加載配置資訊,Spring Cloud Config實作了對服務端和客戶端中環境變數和屬性配置的抽象映射,所以它除了適用于Spring構建的應用程式之外,也可以在任何其他語言運行的應用程式中使用,由于Spring Cloud Config實作的配置中心默認采用Git來存盤配置資訊,所以使用Spring Cloud Config構建的配置服務器,天然就支持對微服務應用配置資訊的版本管理,并且可以通過Git客戶端工具來方便的管理和訪問配置內容,當然它也提供了對其他存盤方式的支持,比如:SVN倉庫、本地化檔案系統,
貳、準備作業
- 首先在工程下面新建lovin-config-repo,作為存放組態檔的地方,并且添加dev,test,pro的相關組態檔,最后在組態檔中添加token的配置,具體見下圖


- 新建一個config的服務端子工程lovin-config-server,用于后面的操作,下面是主要的pom依賴:
<parent>
<artifactId>lovincloud</artifactId>
<groupId>com.eelve.lovincloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lovin-config-server</artifactId>
<packaging>jar</packaging>
<name>lovinconfigserver</name>
<version>0.0.1</version>
<description>配置服務端</description>
<dependencies>
<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-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
- 這里為了安全,我這里還是添加spring-boot-starter-security
server:
port: 8886 # 服務埠號
spring:
application:
name: lovinconfigserver # 服務名稱
security:
basic:
enabled: true
user:
name: lovin
password: ${REGISTRY_SERVER_PASSWORD:lovin}
cloud:
config:
server:
git:
uri: https://github.com/lovinstudio/lovincloud
search-paths: lovin-config-repo
label: master
eureka:
client:
serviceUrl:
defaultZone: http://lovin:lovin@localhost:8881/eureka/ # 注冊到的eureka服務地址
- 上面的組態檔是用git作為組態檔管理中心,還有svn和本地檔案系統兩種,我這里也在下面簡單羅列以下:
git版本配置
spring:
cloud:
config:
server:
git:
uri: https://github.com/lovinstudio/lovincloud
search-paths: lovin-config-repo
username: #如果是私人倉庫,還需要配置用戶名,公共倉庫可以省略
password: #如果是私人倉庫,還需要配置密碼,公共倉庫可以省略
label: master
svn版本配置
spring:
cloud:
config:
server:
svn:
uri: http://192.168.0.6/svn/repo/config-repo
username: username
password: password
default-label: trunk
profiles:
active: subversion #這里需要顯式宣告為subversion
同時還需要引入相應的配置:
<!--SVN-->
<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit</artifactId>
</dependency>
本地版本配置
spring:
cloud:
config:
server:
native:
searchLocations: file:D:\\config #classpath:/config
profiles:
active: native #native
- 配置spring-boot-starter-security,這里為了方便我這里放開所有請求
package com.eelve.lovin.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @ClassName WebSecurityConfig
* @Description TDO
* @Author zhao.zhilue
* @Date 2019/8/18 13:52
* @Version 1.0
**/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()
.and().csrf().disable();
}
}
- 在主類上添加@EnableConfigServer,當然也需要注冊到注冊中心:
package com.eelve.lovin;
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;
/**
* @ClassName LovinEurekaClientApplication
* @Description TDO
* @Author zhao.zhilue
* @Date 2019/8/15 16:37
* @Version 1.0
**/
@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class LovinConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(LovinConfigServerApplication.class,args);
}
}
叁、啟動測驗
- 依次啟動eureka的服務端和新建的lovin-config-server
- 訪問地址:http://chirius:8886/lovin-config/dev,
- 結果原始資料:
{"name":"lovin-config","profiles":["dev"],"label":null,"version":"f0aeca26887490e3bcb8be317d4dfb378313a76f","state":null,"propertySources":[{"name":"https://github.com/lovinstudio/lovincloud/lovin-config-repo/lovin-config-dev.properties","source":{"lovin.token":"lovin"}}]}
這時我們通過瀏覽器、POSTMAN或CURL等工具直接來訪問到我們的配置內容了,訪問配置資訊的URL與組態檔的映射關系如下:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
上面的url會映射{application}-{profile}.properties對應的組態檔,其中{label}對應Git上不同的分支,默認為master,我們可以嘗試構造不同的url來訪問不同的配置內容,比如,要訪問master分支,config-client應用的dev環境,就可以訪問這個url:http://chirius:8806/lovin-config/dev,并獲得如下回傳:

這里有一點疑問,我通過http://localhost:8886/lovin-config/dev/去訪問是一直不成功的,但是在換成其他github上面別人的配置倉庫又是可以直接訪問的
2019-08-19 12:55:54.686 INFO 9256 --- [nio-8886-exec-4] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/C:/Users/Chirius/AppData/Local/Temp/config-repo-8280352825025657146/lovin-config-repo/lovin-config-dev.properties
2019-08-19 12:55:57.560 INFO 9256 --- [nio-8886-exec-2] o.s.cloud.commons.util.InetUtils : Cannot determine local hostname
2019-08-19 12:55:57.576 INFO 9256 --- [nio-8886-exec-2] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/C:/Users/Chirius/AppData/Local/Temp/config-repo-8280352825025657146/lovin-config-repo/lovin-config-dev.properties
2019-08-19 12:56:00.544 INFO 9256 --- [nio-8886-exec-1] o.s.cloud.commons.util.InetUtils : Cannot determine local hostname
2019-08-19 12:56:00.559 INFO 9256 --- [nio-8886-exec-1] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/C:/Users/Chirius/AppData/Local/Temp/config-repo-8280352825025657146/lovin-config-repo/lovin-config-dev.properties
2019-08-19 12:56:07.136 INFO 9256 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
2019-08-19 13:01:07.140 INFO 9256 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
2019-08-19 13:06:07.142 INFO 9256 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
ps:通過日志我們可以看到組態檔是被保存在我們本地的,當然我們也就可以通過配置,修改保存的路徑,具體配置為:basedir
肆、新建配置客戶端
新建一個config的服務端子工程lovin-config-client,用于后面的操作,下面是主要的pom依賴:
<parent>
<artifactId>lovincloud</artifactId>
<groupId>com.eelve.lovincloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lovin-config-client</artifactId>
<packaging>jar</packaging>
<name>lovinconfigclient</name>
<version>0.0.1</version>
<description>配置消費端</description>
<dependencies>
<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-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
ps:在這里為了監控配置變化我們需要添加spring-boot-starter-actuator的依賴
- 這里為了安全,我這里還是添加spring-boot-starter-security的配置
- 新建bootstrap.yml
spring:
cloud:
config:
name: lovin-config
profile: dev
uri: http://localhost:8886/
label: master
eureka:
client:
serviceUrl:
defaultZone: http://lovin:lovin@localhost:8881/eureka/ # 注意在高可用的時候需要見注冊中心配置移到該檔案中,在application.yml中見會讀取不到配置
- 添加application.yml
server:
port: 8807 # 服務埠號
spring:
application:
name: lovinconfigclient # 服務名稱
security:
basic:
enabled: true
user:
name: lovin
password: ${REGISTRY_SERVER_PASSWORD:lovin}
- 配置spring-boot-starter-security,這里為了方便我這里放開所有請求
package com.eelve.lovin.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @ClassName WebSecurityConfig
* @Description TDO
* @Author zhao.zhilue
* @Date 2019/8/20 16:59
* @Version 1.0
**/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()
.and().csrf().disable();
}
}
- 我們需要注冊到注冊中心:
package com.eelve.lovin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @ClassName LovinEurekaClientApplication
* @Description TDO
* @Author zhao.zhilue
* @Date 2019/8/15 16:37
* @Version 1.0
**/
@SpringBootApplication
@EnableEurekaClient
public class LovinConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(LovinConfigClientApplication.class,args);
}
}
- 添加ConfigController用來測驗獲取配置
package com.eelve.lovin.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName ConfigController
* @Description TDO
* @Author zhao.zhilue
* @Date 2019/8/20 17:17
* @Version 1.0
**/
@RestController
@RefreshScope // 使用該注解的類,會在接到SpringCloud配置中心配置重繪的時候,自動將新的配置更新到該類對應的欄位中,
public class ConfigController {
@Value("${lovin.token}")
private String token;
@RequestMapping("/token")
public String getToken() {
return this.token;
}
}
PS:其中RefreshScope注解是為了重繪配置來添加的,這樣讓配置倉庫中的配置發生改變的時候,我們可以通過訪問/refresh請求來重繪配置(由spring-boot-starter-actuator提供的監控功能)
通過客戶端去訪問獲取配置資料
-
訪問http://localhost:8807/token,見下圖

-
修改配置,然后再次訪問,我們可以看到配置是沒有變更的


-
重繪配置再次訪問

可以看到這是我們已經獲取到了最新的配置,當時這樣就存在一個問題,每一個配置客戶端都需要重繪配置,會非常麻煩,也很容易出錯,解決方案由webhook來重繪配置,但是這個不是最好的解決辦法,但是我們可以通過訊息總線來解決,這里見會在下一篇文章中詳細講解,在這里就不作贅述了,
- 最后的最后是本博客的原始碼,歡迎關注這一套SpringCloud的實踐
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/243473.html
標籤:Java
