使用Spring Cloud Config統一管理配置,別再到處放配置檔案了
阿新 • • 發佈:2020-08-23
# 1 前言
> 歡迎訪問[南瓜慢說 www.pkslow.com](https://www.pkslow.com/)獲取更多精彩文章!
可配置是一個成熟軟體系統應該提供的特性,而配置管理對於大型系統就顯得十分重要,特別是對於擁有多個應用的微服務系統。可喜的是,`Spring`為我們提供了很好的配置管理,如`Springboot`的配置就很強大。對於`Spring Cloud`,就有強大的`Spring Cloud Config`,在提供了一個在應用之外的配置管理,如檔案或`Git`倉庫,對分散式系統配置管理十分有益。
# 2 快速體驗
`Spring Cloud Config`服務端就是一個`Springboot`應用,啟動、部署都十分簡單。
整體的架構如下圖所示:
![](https://img2020.cnblogs.com/other/946674/202008/946674-20200823004436105-555030701.png)
## 2.1 服務端就是一個Springboot
在`Springboot`中新增依賴如下:
```xml
```
只需要一個就行了,它已經包含了`web`和`actuator`。
新增`Java`主類:
```java
package com.pkslow.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
public static void main(String[] args) {
SpringApplication.run(ConfigServer.class,args);
}
}
```
跟普通的`Springboot`應用相比只是多了一個註解`@EnableConfigServer`而已。
## 2.2 配置倉庫
通過我們會把配置通過版本控制管理起來,一般使用`Git`倉庫,為簡單展示使用本地倉庫如下:
```bash
# 建立目錄
mkdir git-repo
# 初始化一個git目錄
git init
# 新建檔案
touch application.properties
# 新增變更
git add .
# 提交變更
git commit -m "init"
```
配置一下專案的`application.properties`,注意是`Config Server`專案的,而不是在`git-repo`目錄裡的:
```properties
server.port=8888
spring.application.name=config-server
spring.cloud.config.server.git.uri=/Users/pkslow/IdeaProjects/pkslow-modules/config-server/git-repo
```
接著就可以啟動`Config Server`了。
但`git`倉庫裡的配置檔案沒有什麼內容,我們加入以下內容並提交(必須要提交,不然無法獲取)。
```properties
pkslow.webSite=www.pkslow.com
pkslow.age=18
[email protected]
```
## 2.3 配置路徑匹配
那我們如何獲取這些配置呢?可以通過以下`URL`讀取:
```bash
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
```
- `label`指的是程式碼分支,如`master`,`feature-1`等。
- `application`是應用的名字,在以後客戶端讀取會用到。
- `profile`一般用於指定環境,如`prod`,`dev`,`uat`等。
所以,我們可以用以下`URL`來獲取我們剛新增的配置資訊:
```bash
http://localhost:8888/application/default
http://localhost:8888/application/default/master
http://localhost:8888/master/application.properties
http://localhost:8888/application-default.properties
```
訪問如下:
```bash
$ curl http://localhost:8888/application/default/master
{"name":"application","profiles":["default"],"label":"master","version":"8796f39b35095f6e9b7176457eb03dd6d62b1783","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/git-repo/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.age":"18","pkslow.email":"[email protected]"}}]}
```
最後一個地址`/{label}/{application}-{profile}.properties`的返回結果格式不同,直接返回配置檔案內容:
```bash
$ curl http://localhost:8888/application-default.properties
pkslow.age: 18
pkslow.email: [email protected]
pkslow.webSite: www.pkslow.com
```
如果我們先建一個分支`release-20200809`,並修改`age`為實際年齡`9`,則如下:
```bash
$ curl http://localhost:8888/application/default/release-20200809
{"name":"application","profiles":["default"],"label":"release-20200809","version":"7e27e6972ed31ee1a51e9277a2f5c0a628cec67a","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/git-repo/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.age":"9","pkslow.email":"[email protected]"}}]}
```
可以看到對應的`pkslow.age`已經變為`9`了,但訪問`/application/default/master`則還是`18`,分支之間不會相互影響。
## 2.4 遠端倉庫
本地倉庫只是為了簡單展示,在實際專案中,一般使用遠端倉庫,在`GitHub`建立一個新的倉庫如下:
![](https://img2020.cnblogs.com/other/946674/202008/946674-20200823004436495-2129000366.png)
特意建立了個`private`的倉庫來檢測後面的鑑權是否正確。
重新配置倉庫的地址如下:
```properties
spring.cloud.config.server.git.uri=https://github.com/pkslow/pkslow-config
[email protected]
spring.cloud.config.server.git.password=***
spring.cloud.config.server.git.default-label=master
spring.cloud.config.server.git.search-paths=demo
```
建立一個`demo`目錄來放置配置,所以`search-paths`配置為`demo`。完成配置重啟伺服器,就可以正常讀取遠端倉庫的配置了。
## 2.5 多個程式碼配置倉庫
有些時候,我們的配置可能並不只在一個倉庫裡,而是在各自客戶端的程式碼庫中,比如我們有以下三個服務:
- (1)服務發現:discovery,程式碼庫pkslow-discovery-service
- (2)API閘道器:gateway,程式碼庫pkslow-gateway-service
- (3)訂單服務:order,程式碼庫pkslow-order-service
它們各自的配置檔案都放在各自的程式碼庫裡,那就需要配置多個程式碼庫。我們還多配置一個預設的配置庫pkslow-default,如果匹配不到,就會選擇預設程式碼庫的配置。具體配置如下:
```yaml
server:
port: 8888
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: /Users/pkslow/multiple-repos/pkslow-default
repos:
pkslow-discovery-service:
pattern: pkslow-discovery-*
cloneOnStart: true
uri: /Users/pkslow/multiple-repos/pkslow-discovery-service
search-paths: config
pkslow-gateway-service:
pattern: pkslow-gateway-*/dev
cloneOnStart: true
uri: /Users/pkslow/multiple-repos/pkslow-gateway-service
search-paths: config
pkslow-order-service:
pattern: pkslow-order-*
cloneOnStart: true
uri: /Users/pkslow/IdeaProjects/pkslow-order-service
search-paths: config
```
可以各自定義配置檔案所放的目錄`search-paths`,不配置預設為根目錄。
這裡的`pattern`的配置規則是`{application}/{profile}`,支援正則符號`*`。注意只匹配一個結果,如果都滿足,只取第一個匹配的倉庫。
啟動後我們來看看配置結果:
```bash
# 預設profile和label,正確匹配
$ curl http://localhost:8888/pkslow-order-service/default/master
{"name":"pkslow-order-service","profiles":["default"],"label":"master","version":"9d86e5d11974f0a0e7c20cd53d8f062755193e70","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-order-service/config/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.app.name":"order-service"}}]}
# 正確匹配,但不存在的Label,配置庫沒有對應程式碼分支,404
$ curl http://localhost:8888/pkslow-order-service/default/release
{"timestamp":"2020-08-13T06:58:38.722+0000","status":404,"error":"Not Found","message":"No such label: release","path":"/pkslow-order-service/default/release"}
# profile為dev,正確匹配
$ curl http://localhost:8888/pkslow-order-service/dev/master
{"name":"pkslow-order-service","profiles":["dev"],"label":"master","version":"9d86e5d11974f0a0e7c20cd53d8f062755193e70","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-order-service/config/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.app.name":"order-service"}}]}
# 對於gateway只能匹配profile=dev,無法匹配,讀取預設配置
$ curl http://localhost:8888/pkslow-gateway-service/default/master
{"name":"pkslow-gateway-service","profiles":["default"],"label":"master","version":"8358f2b4701fac21a0c7776bc46cec6d9442c549","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-base/application.properties","source":{"pkslow.birthDate":"2020-08-10"}}]}
# 對於gateway只能匹配profile=dev,正確匹配
$ curl http://localhost:8888/pkslow-gateway-service/dev/master
{"name":"pkslow-gateway-service","profiles":["dev"],"label":"master","version":"1a4e26849b237dc2592ca0d391daaa1a879747d2","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-gateway-service/config/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.app.name":"gateway-service"}}]}
# 不存在的服務名,無法匹配,讀取預設配置
$ curl http://localhost:8888/unknown-service/dev/master
{"name":"unknown-service","profiles":["dev"],"label":"master","version":"8358f2b4701fac21a0c7776bc46cec6d9442c549","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-base/application.properties","source":{"pkslow.birthDate":"2020-08-10"}}]}
```
# 3 客戶端使用配置
經過前面的例子我們已經瞭解到服務端如何從程式碼庫裡獲取配置,但始終還是要使客戶端能獲取到對應的配置併產生效果。我們來演示一下。
## 3.1 專案準備
搭建一個最簡單的`Springboot Web`專案,並加上`Spring Cloud Config`的支援,新增依賴如下:
```xml
```
新增配置檔案:`bootstrap.properties`(雖然我們要從服務端讀取配置,但有些配置還是必須在客戶新增的,如服務端地址),內容如下:
```properties
server.port=8080
spring.application.name=pkslow-gateway-service
spring.cloud.config.uri=http://localhost:8888
```
在這裡我們配置了客戶端的埠、服務端的地址以及客戶端應用的名字,這個名字是非常關鍵的,待會講解。
新增`Controller`來暴露`API`以顯示讀到的配置內容:
```java
@RestController
public class PkslowController {
@Value("${pkslow.age}")
private Integer age;
@Value("${pkslow.email}")
private String email;
@Value("${pkslow.webSite}")
private String webSite;
@GetMapping("/pkslow")
public Map