Spring Cloud Config中文文件
目錄
1.3.0.RELEASE
Spring Cloud Config為分散式系統中的外部配置提供伺服器和客戶端支援。使用Config Server,您可以在所有環境中管理應用程式的外部屬性。客戶端和伺服器上的概念對映與Spring Environment
和PropertySource
抽象相同,因此它們與Spring應用程式非常契合,但可以與任何以任何語言執行的應用程式一起使用。隨著應用程式通過從開發人員到測試和生產的部署流程,您可以管理這些環境之間的配置,並確定應用程式具有遷移時需要執行的一切。伺服器儲存後端的預設實現使用git,因此它輕鬆支援標籤版本的配置環境,以及可以訪問用於管理內容的各種工具。可以輕鬆新增替代實現,並使用Spring配置將其插入。
快速開始
啟動伺服器:
$ cd spring-cloud-config-server
$ ../mvnw spring-boot:run
該伺服器是一個Spring Boot應用程式,所以你可以從IDE執行它,而不是喜歡(主類是ConfigServerApplication
)。然後嘗試一個客戶端:
$ curl localhost:8888/foo/development {"name":"development","label":"master","propertySources":[ {"name":"https://github.com/scratches/config-repo/foo-development.properties","source":{"bar":"spam"}}, {"name":"https://github.com/scratches/config-repo/foo.properties","source":{"foo":"bar"}} ]}
定位資源的預設策略是克隆一個git倉庫(在spring.cloud.config.server.git.uri
),並使用它來初始化一個迷你SpringApplication
。迷你應用程式的Environment
用於列舉屬性源並通過JSON端點發布。
HTTP服務具有以下格式的資源:
/{application}/{profile}[/{label}] /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties
其中“應用程式”作為SpringApplication
中的spring.config.name
注入(即常規Spring Boot應用程式中通常為“應用程式”),“配置檔案”是活動配置檔案(或逗號分隔列表)的屬性),“label”是可選的git標籤(預設為“master”)。
Spring Cloud Config伺服器從git儲存庫中提取遠端客戶端的配置(必須提供):
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
客戶端使用
要在應用程式中使用這些功能,只需將其構建為依賴於spring-cloud-config-client的Spring Boot應用程式(例如,檢視配置客戶端或示例應用程式的測試用例)。新增依賴關係的最方便的方法是通過Spring Boot啟動器org.springframework.cloud:spring-cloud-starter-config
。還有一個Maven使用者的父pom和BOM(spring-cloud-starter-parent
)和用於Gradle和Spring CLI使用者的Spring IO版本管理屬性檔案。示例Maven配置:
的pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!-- repositories also needed for snapshots and milestones -->
那麼你可以建立一個標準的Spring Boot應用程式,就像這個簡單的HTTP伺服器:
@SpringBootApplication
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello World!";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
當它執行它將從埠8888上的預設本地配置伺服器接收外部配置,如果它正在執行。要修改啟動行為,您可以使用bootstrap.properties
(如application.properties
,但是應用程式上下文的引導階段)更改配置伺服器的位置,例如
spring.cloud.config.uri: http://myconfigserver.com
引導屬性將在/env
端點中顯示為高優先順序屬性源,例如
$ curl localhost:8080/env
{
"profiles":[],
"configService:https://github.com/spring-cloud-samples/config-repo/bar.properties":{"foo":"bar"},
"servletContextInitParams":{},
"systemProperties":{...},
...
}
(名為“configService:<遠端儲存庫的URL> / <檔名>”的屬性源包含值為“bar”的屬性“foo”,是最高優先順序)。
注意 |
屬性源名稱中的URL是git儲存庫,而不是配置伺服器URL。 |
Spring Cloud Config伺服器
伺服器為外部配置(名稱值對或等效的YAML內容)提供了基於資源的HTTP。伺服器可以使用@EnableConfigServer
註釋輕鬆嵌入到Spring Boot應用程式中。所以這個應用程式是一個配置伺服器:
ConfigServer.java
@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
public static void main(String[] args) {
SpringApplication.run(ConfigServer.class, args);
}
}
像所有預設情況下在埠8080上執行的所有Spring Boot應用程式一樣,但您可以通過各種方式將其切換到常規埠8888。最簡單的設定預設配置儲存庫是通過使用spring.config.name=configserver
啟動(在Config Server jar中有一個configserver.yml
)。另一個是使用你自己的application.properties
,例如
application.properties
server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo
其中${user.home}/config-repo
是包含YAML和屬性檔案的git倉庫。
提示 |
以下是上面示例中建立git倉庫的方法:
|
警告 |
使用本地檔案系統進行git儲存庫僅用於測試。使用伺服器在生產環境中託管配置庫。 |
警告 |
如果您只保留文字檔案,則配置庫的初始克隆將會快速有效。如果您開始儲存二進位制檔案,尤其是較大的檔案,則可能會遇到伺服器中第一個配置請求和/或記憶體不足錯誤的延遲。 |
環境庫
您要在哪裡儲存配置伺服器的配置資料?管理此行為的策略是EnvironmentRepository
,服務於Environment
物件。這個Environment
是Spring Environment
(包括propertySources
作為主要功能)的域的淺層副本。Environment
資源由三個變數引數化:
-
{application}
對映到客戶端的“spring.application.name”; -
{profile}
對映到客戶端上的“spring.profiles.active”(逗號分隔列表); 和 -
{label}
這是一個伺服器端功能,標記“版本”的一組配置檔案。
儲存庫實現通常表現得像一個Spring Boot應用程式從“spring.config.name”等於{application}
引數載入配置檔案,“spring.profiles.active”等於{profiles}
引數。配置檔案的優先順序規則也與常規啟動應用程式中的相同:活動配置檔案優先於預設配置,如果存在多個配置檔案,則最後一個配置檔案(例如向Map
新增條目))。
示例:客戶端應用程式具有此引導配置:
bootstrap.yml
spring:
application:
name: foo
profiles:
active: dev,mysql
(像往常一樣使用Spring Boot應用程式,這些屬性也可以設定為環境變數或命令列引數)。
如果儲存庫是基於檔案的,則伺服器將從application.yml
建立Environment
(在所有客戶端之間共享),foo.yml
(以foo.yml
優先))。如果YAML檔案在其中具有指向Spring配置檔案的文件,則應用較高優先順序(按照列出的配置檔案的順序),並且如果存在特定於配置檔案的YAML(或屬性)檔案,那麼這些檔案也應用的優先順序高於預設值。較高優先順序轉換為Environment
之前列出的PropertySource
。(這些規則與獨立的Spring Boot應用程式相同。)
Git後端
EnvironmentRepository
的預設實現使用Git後端,這對於管理升級和物理環境以及稽核更改非常方便。要更改儲存庫的位置,可以在Config Server中設定“spring.cloud.config.server.git.uri”配置屬性(例如application.yml
)。如果您使用file:
字首進行設定,則應從本地儲存庫中執行,以便在沒有伺服器的情況下快速方便地啟動,但在這種情況下,伺服器將直接在本地儲存庫中進行操作,而不會克隆它如果它不是裸機,因為配置伺服器永遠不會更改“遠端”資源庫)。要擴充套件Config Server並使其高度可用,您需要將伺服器的所有例項指向同一個儲存庫,因此只有共享檔案系統才能正常工作。即使在這種情況下,最好使用共享檔案系統儲存庫的ssh:
協議,以便伺服器可以將其克隆並使用本地工作副本作為快取。
該儲存庫實現將HTTP資源的{label}
引數對映到git標籤(提交ID,分支名稱或標籤)。如果git分支或標籤名稱包含斜槓(“/”),則應使用特殊字串“(_)”指定HTTP URL中的標籤,以避免與其他URL路徑模糊。例如,如果標籤是foo/bar
,則替換斜槓將導致類似於foo(_)bar
的標籤。如果您使用像curl這樣的命令列客戶端(例如使用引號將其從shell中轉出來),請小心URL中的方括號。
Git URI中的佔位符
Spring Cloud Config伺服器支援一個Git倉庫URL,其中包含{application}
和{profile}
(以及{label}
)的佔位符,如果需要,請記住,標籤應用為git標籤)。因此,您可以使用(例如)輕鬆支援“每個應用程式的一個repo”策略:
spring:
cloud:
config:
server:
git:
uri: https://github.com/myorg/{application}
或使用類似模式“{一個回報每個配置檔案”策略,但使用{profile}
。
模式匹配和多個儲存庫
還可以通過應用程式和配置檔名稱的模式匹配來支援更復雜的需求。模式格式是帶有萬用字元的{application}/{profile}
名稱的逗號分隔列表(其中以萬用字元開頭的模式可能需要引用)。例:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
repos:
simple: https://github.com/simple/config-repo
special:
pattern: special*/dev*,*special*/dev*
uri: https://github.com/special/config-repo
local:
pattern: local*
uri: file:/home/configsvc/config-repo
如果{application}/{profile}
不匹配任何模式,它將使用在“spring.cloud.config.server.git.uri”下定義的預設uri。在上面的例子中,對於“簡單”儲存庫,模式是simple/*
(即所有配置檔案中只匹配一個名為“簡單”的應用程式)。“本地”儲存庫與所有配置檔案中以“local”開頭的所有應用程式名稱匹配(將/*
字尾自動新增到任何沒有配置檔案匹配器的模式)。
注意 |
在上述“簡單”示例中使用的“單行”快捷方式只能在唯一要設定的屬性為URI的情況下使用。如果您需要設定其他任何內容(憑據,模式等),則需要使用完整的表單。 |
repo中的pattern
屬性實際上是一個數組,因此您可以使用屬性檔案中的YAML陣列(或[0]
,[1]
等字尾)繫結到多個模式。如果要執行具有多個配置檔案的應用程式,則可能需要執行此操作。例:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
repos:
development:
pattern:
- */development
- */staging
uri: https://github.com/development/config-repo
staging:
pattern:
- */qa
- */production
uri: https://github.com/staging/config-repo
注意 |
Spring Cloud將猜測包含不在* 中的配置檔案的模式意味著您實際上希望匹配從該模式開始的配置檔案列表(所以*/staging 是["*/staging", "*/staging,*"] 的快捷方式) 。這是常見的,您需要在本地的“開發”配置檔案中執行應用程式,但也可以遠端執行“雲”配置檔案。 |
每個儲存庫還可以選擇將配置檔案儲存在子目錄中,搜尋這些目錄的模式可以指定為searchPaths
。例如在頂層:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
searchPaths: foo,bar*
在此示例中,伺服器搜尋頂級和“foo /”子目錄以及名稱以“bar”開頭的任何子目錄中的配置檔案。
預設情況下,首次請求配置時,伺服器克隆遠端儲存庫。伺服器可以配置為在啟動時克隆儲存庫。例如在頂層:
spring:
cloud:
config:
server:
git:
uri: https://git/common/config-repo.git
repos:
team-a:
pattern: team-a-*
cloneOnStart: true
uri: http://git/team-a/config-repo.git
team-b:
pattern: team-b-*
cloneOnStart: false
uri: http://git/team-b/config-repo.git
team-c:
pattern: team-c-*
uri: http://git/team-a/config-repo.git
在此示例中,伺服器在啟動之前克隆了team-a的config-repo,然後它接受任何請求。所有其他儲存庫將不被克隆,直到請求從儲存庫配置。
注意 |
在配置伺服器啟動時設定要克隆的儲存庫可以幫助在配置伺服器啟動時快速識別錯誤配置的源(例如,無效的儲存庫URI)。配置源不啟用cloneOnStart 時,配置伺服器可能啟動成功配置錯誤或無效的配置源,並且不會檢測到錯誤,直到應用程式從該配置源請求配置為止。 |
認證
要在遠端儲存庫上使用HTTP基本身份驗證,請分別新增“username”和“password”屬性(不在URL中),例如
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
username: trolley
password: strongpassword
如果您不使用HTTPS和使用者憑據,則在將金鑰儲存在預設目錄(~/.ssh
)中,並且uri指向SSH位置時,SSH也應該開箱即用,例如“ [email protected]:配置/雲配置”。重要的是,Git伺服器的條目存在於~/.ssh/known_hosts
檔案中,並且格式為ssh-rsa
。不支援其他格式(如ecdsa-sha2-nistp256
)。為了避免意外,您應該確保Git伺服器的known_hosts
檔案中只有一個條目存在,並且與您提供給配置伺服器的URL匹配。如果您在URL中使用了一個主機名,那麼您希望在known_hosts
檔案中具有該主機名,而不是IP。使用JGit訪問儲存庫,因此您發現的任何文件都應適用。HTTPS代理設定可以~/.git/config
設定,也可以通過系統屬性(-Dhttps.proxyHost
和-Dhttps.proxyPort
)與任何其他JVM程序相同。
提示 |
如果您不知道~/.git 目錄在何處使用git config --global 操縱設定(例如git config --global http.sslVerify false )。 |
使用AWS CodeCommit進行認證
AWS CodeCommit認證也可以完成。當從命令列使用Git時,AWS CodeCommit使用身份驗證助手。該幫助器不與JGit庫一起使用,因此如果Git URI與AWS CodeCommit模式匹配,則將建立用於AWS CodeCommit的JGit CredentialProvider。AWS CodeCommit URI始終看起來像 https://git-codecommit.$ {AWS_REGION} .amazonaws.com / $ {repopath}。
如果您使用AWS CodeCommit URI提供使用者名稱和密碼,那麼這些URI必須 是用於訪問儲存庫的AWS accessKeyId和 secretAccessKey。如果不指定使用者名稱和密碼,則將使用AWS預設憑據提供程式鏈檢索accessKeyId和secretAccessKey 。
如果您的Git URI與CodeCommit URI模式(上述)匹配,則必須在使用者名稱和密碼或預設憑據提供程式鏈支援的某個位置中提供有效的AWS憑據。AWS EC2例項可以使用EC2例項的 IAM角色。
注意:aws-java-sdk-core jar是一個可選的依賴關係。如果aws-java-sdk-core jar不在您的類路徑上,則無論git伺服器URI如何,都將不會建立AWS程式碼提交憑據提供程式。
Git搜尋路徑中的佔位符
Spring Cloud Config伺服器還支援{application}
和{profile}
(以及{label}
(如果需要))佔位符的搜尋路徑。例:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
searchPaths: '{application}'
在資源庫中搜索與目錄(以及頂級)相同名稱的檔案。萬用字元在具有佔位符的搜尋路徑中也是有效的(搜尋中包含任何匹配的目錄)。
力拉入Git儲存庫
如前所述Spring Cloud Config伺服器克隆遠端git儲存庫,如果某種方式本地副本變髒(例如,由作業系統程序更改資料夾內容),則Spring Cloud Config伺服器無法從遠端儲存庫更新本地副本。
要解決這個問題,有一個force-pull
屬性將使Spring Cloud Config Server強制從遠端儲存庫中提取,如果本地副本是髒的。例:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
force-pull: true
如果您有多個儲存庫配置,則可以為每個儲存庫配置force-pull
屬性。例:
spring:
cloud:
config:
server:
git:
uri: https://git/common/config-repo.git
force-pull: true
repos:
team-a:
pattern: team-a-*
uri: http://git/team-a/config-repo.git
force-pull: true
team-b:
pattern: team-b-*
uri: http://git/team-b/config-repo.git
force-pull: true
team-c:
pattern: team-c-*
uri: http://git/team-a/config-repo.git
注意 |
force-pull 屬性的預設值為false 。 |
版本控制後端檔案系統使用
警告 |
使用基於VCS的後端(git,svn)檔案被檢出或克隆到本地檔案系統。預設情況下,它們放在系統臨時目錄中,字首為config-repo- 。在linux上,例如可以是/tmp/config-repo-<randomid> 。一些作業系統會定期清除臨時目錄。這可能會導致意外的行為,例如缺少屬性。為避免此問題,請通過將spring.cloud.config.server.git.basedir 或spring.cloud.config.server.svn.basedir 設定為不在系統臨時結構中的目錄來更改Config Server所使用的目錄。 |
檔案系統後端
配置伺服器中還有一個不使用Git的“本機”配置檔案,只是從本地類路徑或檔案系統載入配置檔案(您想要指向的任何靜態URL“spring.cloud.config.server .native.searchLocations“)。要使用本機配置檔案,只需使用“spring.profiles.active = native”啟動Config Server。
注意 |
記住使用file: 字首的檔案資源(預設沒有字首通常是classpath)。與任何Spring Boot配置一樣,您可以嵌入${} 樣式的環境佔位符,但請記住,Windows中的絕對路徑需要額外的“/”,例如 |
警告 |
searchLocations 的預設值與本地Spring Boot應用程式(所以[classpath:/, classpath:/config, file:./, file:./config] )相同。這不會將application.properties 從伺服器暴露給所有客戶端,因為在傳送到客戶端之前,伺服器中存在的任何屬性源都將被刪除。 |
提示 |
檔案系統後端對於快速入門和測試是非常好的。要在生產中使用它,您需要確保檔案系統是可靠的,並在配置伺服器的所有例項中共享。 |
搜尋位置可以包含{application}
,{profile}
和{label}
的佔位符。以這種方式,您可以隔離路徑中的目錄,並選擇一個有用的策略(例如每個應用程式的子目錄或每個配置檔案的子目錄)。
如果您不在搜尋位置使用佔位符,則該儲存庫還將HTTP資源的{label}
引數附加到搜尋路徑上的字尾,因此屬性檔案將從每個搜尋位置載入並具有相同名稱的子目錄作為標籤(標籤屬性在Spring環境中優先)。因此,沒有佔位符的預設行為與新增以/{label}/. For example `file:/tmp/config
結尾的搜尋位置的新增與file:/tmp/config,file:/tmp/config/{label}
相同
Vault後端
Spring Cloud Config伺服器還支援Vault作為後端。
Vault是安全訪問祕密的工具。一個祕密是你想要嚴格控制訪問的任何東西,如API金鑰,密碼,證書等等。Vault為任何祕密提供統一的介面,同時提供嚴格的訪問控制和記錄詳細的稽核日誌。
有關Vault的更多資訊,請參閱Vault快速入門指南。
要使配置伺服器使用Vault後端,必須使用vault
配置檔案執行配置伺服器。例如在配置伺服器的application.properties
中,您可以新增spring.profiles.active=vault
。
預設情況下,配置伺服器將假定您的Vault伺服器正在執行。它還將假設後端名稱為secret
,金鑰為application
。所有這些預設值都可以在配置伺服器的application.properties
中配置。以下是可配置的Vault屬性表。所有屬性字首為spring.cloud.config.server.vault
。
名稱 | 預設值 |
---|---|
主辦 |
127.0.0.1 |
港口 |
8200 |
方案 |
HTTP |
後端 |
祕密 |
defaultKey |
應用 |
profileSeparator |
, |
所有可配置的屬性可以在org.springframework.cloud.config.server.environment.VaultEnvironmentRepository
中找到。
執行您的配置伺服器,您可以向伺服器發出HTTP請求,以從Vault後端檢索值。為此,您將需要一個令牌為您的Vault伺服器。
首先將一些資料放在你身上Vault。例如
$ vault write secret/application foo=bar baz=bam
$ vault write secret/myapp foo=myappsbar
現在,將HTTP請求傳送給您的配置伺服器以檢索值。
$ curl -X "GET" "http://localhost:8888/myapp/default" -H "X-Config-Token: yourtoken"
在提出上述要求後,您應該會看到類似的回覆。
{
"name":"myapp",
"profiles":[
"default"
],
"label":null,
"version":null,
"state":null,
"propertySources":[
{
"name":"vault:myapp",
"source":{
"foo":"myappsbar"
}
},
{
"name":"vault:application",
"source":{
"baz":"bam",
"foo":"bar"
}
}
]
}
多個屬性來源
使用Vault時,您可以為應用程式提供多個屬性源。例如,假設您已將資料寫入Vault中的以下路徑。
secret/myApp,dev
secret/myApp
secret/application,dev
secret/application
寫入secret/application
的屬性可 用於使用配置伺服器的所有應用程式。名稱為myApp
的應用程式將具有寫入secret/myApp
和secret/application
的任何屬性。當myApp
啟用dev
配置檔案時,寫入所有上述路徑的屬性將可用,列表中第一個路徑中的屬性優先於其他路徑。
與所有應用共享配置
基於檔案的儲存庫
使用基於檔案(即git,svn和native)的儲存庫,所有客戶端應用程式(application.properties
,application.yml
,application-*.properties
等))共享檔名為application*
的資源。您可以使用這些檔名的資源來配置全域性預設值,並根據需要將其覆蓋應用程式特定的檔案。
#_property_overrides [屬性覆蓋]功能也可用於設定全域性預設值,並且允許佔位符應用程式在本地覆蓋它們。
提示 |
使用“本機”配置檔案(本地檔案系統後端),建議您使用不屬於伺服器自身配置的顯式搜尋位置。否則,預設搜尋位置中的application* 資源將被刪除,因為它們是伺服器的一部分。 |
Vault伺服器
當使用Vault作為後端時,您可以通過將配置放在secret/application
中與所有應用程式共享配置。例如,如果您執行此Vault命令
$ vault write secret/application foo=bar baz=bam
使用配置伺服器的所有應用程式都可以使用屬性foo
和baz
。
複合環境庫
在某些情況下,您可能希望從多個環境儲存庫中提取配置資料。為此,只需在配置伺服器的應用程式屬性或YAML檔案中啟用多個配置檔案即可。例如,如果您要從Git儲存庫以及SVN儲存庫中提取配置資料,那麼您將為配置伺服器設定以下屬性。
spring:
profiles:
active: git, svn
cloud:
config:
server:
svn:
uri: file:///path/to/svn/repo
order: 2
git:
uri: file:///path/to/git/repo
order: 1
除了指定URI的每個repo之外,還可以指定order
屬性。order
屬性允許您指定所有儲存庫的優先順序順序。order
屬性的數值越低,優先順序越高。儲存庫的優先順序將有助於解決包含相同屬性的值的儲存庫之間的任何潛在衝突。
注意 |
從環境倉庫檢索值時的任何型別的故障將導致整個複合環境的故障。 |
注意 |
當使用複合環境時,重要的是所有repos都包含相同的標籤。如果您有類似於上述的環境,並且使用標籤master 請求配置資料,但是SVN repo不包含稱為master 的分支,則整個請求將失敗。 |
自定義複合環境庫
除了使用Spring Cloud中的一個環境儲存庫之外,還可以提供自己的EnvironmentRepository
bean作為複合環境的一部分。要做到這一點,你的bean必須實現EnvironmentRepository
介面。如果您想在複合環境中控制自定義EnvironmentRepository
的優先順序,您還應該實現Ordered
介面並覆蓋getOrdered
方法。如果您不實現Ordered
介面,則您的EnvironmentRepository
將被賦予最低優先順序。
屬性覆蓋
Config Server具有“覆蓋”功能,允許操作員為所有應用程式提供配置屬性,這些應用程式不會被應用程式使用正常的Spring Boot鉤子意外更改。要宣告覆蓋只是將名稱/值對的地圖新增到spring.cloud.config.server.overrides
。例如
spring:
cloud:
config:
server:
overrides:
foo: bar
將導致配置客戶端的所有應用程式獨立於自己的配置讀取foo=bar
。(當然,應用程式可以以任何方式使用Config Server中的資料,因此覆蓋不可強制執行,但如果它們是Spring Cloud Config客戶端,則它們會提供有用的預設行為。)
提示 |
通常使用“$ {}”的Spring環境佔位符可以使用反斜槓(“\”)來轉義(並在客戶端上解析)來轉義“$”或“{”,例如\${app.foo:bar} 解析為“bar “除非該應用程式提供自己的”app.foo“。請注意,在YAML中,您不需要轉義反斜槓本身,而是在您執行的屬性檔案中配置伺服器上的覆蓋。 |
您可以將客戶端中所有覆蓋的優先順序更改為更為預設值,允許應用程式通過在遠端儲存庫中設定標誌spring.cloud.config.overrideNone=true
(預設值為false),在環境變數或系統屬性中提供自己的值。
健康指標
配置伺服器附帶執行狀況指示器,檢查配置的EnvironmentRepository
是否正常工作。預設情況下,它要求EnvironmentRepository
應用程式名為app
,default
配置檔案和EnvironmentRepository
實現提供的預設標籤。
您可以配置執行狀況指示器以檢查更多應用程式以及自定義配置檔案和自定義標籤,例如
spring:
cloud:
config:
server:
health:
repositories:
myservice:
label: mylabel
myservice-dev:
name: myservice
profiles: development
您可以通過設定spring.cloud.config.server.health.enabled=false
來禁用執行狀況指示器。
安全
您可以以任何對您有意義的方式(從物理網路安全性到OAuth2承載令牌)來保護您的Config Server,而Spring Security和Spring Boot可以輕鬆做任何事情。
要使用預設的Spring Boot配置的HTTP Basic安全性,只需在類路徑中包含Spring Security(例如,通過spring-boot-starter-security
)。預設是“user”的使用者名稱和隨機生成的密碼,這在實踐中不會非常有用,因此我們建議您配置密碼(通過security.user.password
)進行加密(有關以下內容的說明,請參閱以下內容)怎麼做)。
加密和解密
重要 |
先決條件:要使用加密和解密功能,您需要在JVM中安裝全面的JCE(預設情況下不存在)。您可以從Oracle下載“Java加密擴充套件(JCE)無限強度管理策略檔案”,並按照安裝說明(實際上將JRE lib / security目錄中的2個策略檔案替換為您下載的檔案)。 |
如果遠端屬性源包含加密內容(以{cipher}
開頭的值)),則在通過HTTP傳送給客戶端之前,它們將被解密。這種設定的主要優點是,當它們“靜止”時,屬性值不必是純文字(例如在git倉庫中)。如果值無法解密,則從屬性源中刪除該值,並新增具有相同鍵的附加屬性,但以“無效”作為字首。和“不適用”的值(通常為“<n / a>”)。這主要是為了防止密碼被用作密碼並意外洩漏。
如果要為配置客戶端應用程式設定遠端配置儲存庫,可能會包含一個application.yml
,例如:
application.yml
spring:
datasource:
username: dbuser
password: '{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ'
.properties檔案中的加密值不能用引號括起來,否則不會解密該值:
application.properties
spring.datasource.username: dbuser
spring.datasource.password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ
您可以安全地將此純文字推送到共享git儲存庫,並且保密密碼。
伺服器還暴露了/encrypt
和/decrypt
端點(假設這些端點將被保護並且只能由授權代理訪問)。如果您正在編輯遠端配置檔案,可以使用Config Server通過POST到/encrypt
端點來加密值,例如
$ curl localhost:8888/encrypt -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
注意 |
如果要加密的值具有需要進行URL編碼的字元,則應使用--data-urlencode 選項curl 來確保它們已正確編碼。 |
逆向操作也可通過/decrypt
獲得(如果伺服器配置了對稱金鑰或完整金鑰對):
$ curl localhost:8888/decrypt -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret
提示 |
如果您使用curl進行測試,則使用--data-urlencode (而不是-d )或設定顯式Content-Type: text/plain ,以確保在有特殊字元時正確地對資料進行編碼('+'特別是棘手)。 |
在加入值之前,先新增{cipher}
字首,然後再將其放在YAML或屬性檔案中,然後再提交併將其推送到遠端,可能不安全的儲存區。
/encrypt
和/decrypt
端點也都接受/*/{name}/{profiles}
形式的路徑,當客戶端呼叫到主環境資源時,可以使用每個應用程式(名稱)和配置檔案控制密碼。
注意 |
為了以這種細微的方式控制密碼,您還必須提供TextEncryptorLocator 型別的@Bean ,每個名稱和配置檔案都會建立一個不同的加密器。預設提供的不會這樣做(所有加密使用相同的金鑰)。 |
spring
命令列客戶端(安裝了Spring Cloud CLI副檔名)也可用於加密和解密,例如
$ spring encrypt mysecret --key foo
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
$ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret
要在檔案中使用金鑰(例如用於加密的RSA公鑰),使用“@”鍵入鍵值,並提供檔案路徑,例如
$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...
關鍵引數是強制性的(儘管有一個--
字首)。
金鑰管理
Config Server可以使用對稱(共享)金鑰或非對稱金鑰(RSA金鑰對)。非對稱選擇在安全性方面是優越的,但是使用對稱金鑰往往更方便,因為它只是配置的一個屬性值。
要配置對稱金鑰,您只需要將encrypt.key
設定為一個祕密字串(或使用環境變數ENCRYPT_KEY
將其保留為純文字配置檔案)。
要配置非對稱金鑰,您可以將金鑰設定為PEM編碼的文字值(encrypt.key
)或通過金鑰庫(例如由JDK附帶的keytool
實用程式建立)。金鑰庫屬性為encrypt.keyStore.*
,*
等於
-
location
(Resource
位置), -
password
(解鎖金鑰庫)和 -
alias
(以識別商店中使用的金鑰)。
使用公鑰進行加密,需要私鑰進行解密。因此,原則上您只能在伺服器中配置公鑰,如果您只想進行加密(並準備使用私鑰本地解密值)。實際上,您可能不想這樣做,因為它圍繞所有客戶端傳播金鑰管理流程,而不是將其集中在伺服器中。另一方面,如果您的配置伺服器真的相對不安全,並且只有少數客戶端需要加密的屬性,這是一個有用的選項。
建立用於測試的金鑰庫
要建立一個金鑰庫進行測試,您可以執行以下操作:
$ keytool -genkeypair -alias mytestkey -keyalg RSA \
-dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
-keypass changeme -keystore server.jks -storepass letmein
將server.jks
檔案放在類路徑(例如)中,然後在配置伺服器的application.yml
中:
encrypt:
keyStore:
location: classpath:/server.jks
password: letmein
alias: mytestkey
secret: changeme
使用多個鍵和鍵旋轉
除了加密屬性值中的{cipher}
字首之外,配置伺服器在(Base64編碼)密文開始之前查詢{name:value}
字首(零或多個)。金鑰被傳遞給TextEncryptorLocator
,它可以執行找到密碼的TextEncryptor
所需的任何邏輯。如果配置了金鑰庫(encrypt.keystore.location
),預設定位器將使用“key”字首提供的別名,即使用如下密碼來查詢儲存中的金鑰:
foo:
bar: `{cipher}{key:testkey}...`
定位器將尋找一個名為“testkey”的鍵。也可以通過字首中的{secret:…}
值提供一個祕密,但是如果不是預設值,則使用金鑰庫密碼(這是您構建金鑰儲存並且不指定密碼時獲得的密碼)。如果你這樣做 提供一個祕密建議你也加密使用自定義SecretLocator
的祕密。
如果金鑰只用於加密幾個位元組的配置資料(即它們沒有在其他地方使用),則密碼轉換幾乎不是必需的,但是如果存在安全漏洞,有時您可能需要更改金鑰例項。在這種情況下,所有客戶端都需要更改其源配置檔案(例如git),並在所有密碼中使用新的{key:…}
字首,當然,先檢查配置伺服器金鑰庫中的金鑰別名可用。
提示 |
如果要讓Config Server處理所有加密以及解密,也可以將{name:value} 字首新增到釋出到/encrypt 端點的明文。 |
提供加密屬性
有時您希望客戶端在本地解密配置,而不是在伺服器中進行配置。在這種情況下,您仍然可以擁有/加密和/解密端點(如果提供encrypt.*
配置來定位金鑰),但是您需要使用spring.cloud.config.server.encrypt.enabled=false
明確地關閉傳出屬性的解密。如果您不關心端點,那麼如果您既不配置金鑰也不配置使能的標誌,則應該起作用。
服務替代格式
來自環境端點的預設JSON格式對於Spring應用程式的消耗是完美的,因為它直接對映到Environment
抽象。如果您喜歡,可以通過向資源路徑(“.yml”,“.yaml”或“.properties”)新增字尾來使用與YAML或Java屬性相同的資料。這對於不關心JSON端點的結構的應用程式的消費或其提供的額外的元資料可能是有用的,例如,不使用Spring的應用程式可能會受益於此方法的簡單性。
YAML和屬性表示有一個額外的標誌(作為布林查詢引數resolvePlaceholders
提供)),以標示Spring ${…}
形式的原始文件中的佔位符訊號,在渲染之前應儘可能在輸出中解析。這對於不瞭解Spring佔位符約定的消費者來說是一個有用的功能。
注意 |
使用YAML或屬性格式存在侷限性,主要是與元資料的丟失有關。JSON被構造為屬性源的有序列表,例如,名稱與源相關聯。即使源的起源具有多個源,並且原始原始檔的名稱丟失,YAML和屬性表也合併成一個對映。YAML表示不一定是後臺儲存庫中YAML源的忠實表示:它是由平面屬性源的列表構建的,並且必須對鍵的形式進行假設。 |
服務純文字
您的應用程式可能不需要使用Environment
抽象(或YAML中的其他替代表示形式或屬性格式),而是根據自己的環境需要通用的純文字配置檔案。配置伺服器通過/{name}/{profile}/{label}/{path}
中的附加端點提供這些服務,其中“name”,“profile”和“label”的含義與常規環境端點相同,但“path”是檔名(例如log.xml
)。此端點的原始檔位於與環境端點相同的方式:與屬性或YAML檔案相同的搜尋路徑,而不是聚合所有匹配的資源,只返回匹配的第一個。
資源位置後,使用正常格式(${…}
)的佔位符使用提供的應用程式名稱,配置檔案和標籤的有效Environment
來解析。以這種方式,資源端點與環境端點緊密整合。例如,如果您有一個GIT(或SVN)資源庫的佈局:
application.yml
nginx.conf
其中nginx.conf
看起來像這樣:
server {
listen 80;
server_name ${nginx.server.name};
}
和application.yml
這樣:
nginx:
server:
name: example.com
---
spring:
profiles: development
nginx:
server:
name: develop.com
那麼/foo/default/master/nginx.conf
資源如下所示:
server {
listen 80;
server_name example.com;
}
和/foo/development/master/nginx.conf
如下所示:
server {
listen 80;
server_name develop.com;
}
注意 |
就像環境配置的原始檔一樣,“配置檔案”用於解析檔名,所以如果你想要一個特定於檔案的檔案,那麼/*/development/*/logback.xml 將被一個名為logback-development.xml 的檔案解析(優先於logback.xml )。 |
嵌入配置伺服器
配置伺服器最好作為獨立應用程式執行,但如果需要,可以將其嵌入到另一個應用程式中。只需使用@EnableConfigServer
註釋。在這種情況下可以使用的可選屬性是spring.cloud.config.server.bootstrap
,它是一個標誌,表示伺服器應該從自己的遠端儲存庫配置自身。該標誌預設關閉,因為它可能會延遲啟動,但是當嵌入在另一個應用程式中時,以與其他應用程式相同的方式初始化是有意義的。
注意 |
應該很明顯,但是請記住,如果使用引導標誌,配置伺服器將需要在bootstrap.yml 中配置其名稱和儲存庫URI。 |
要更改伺服器端點的位置,您可以(可選)設定spring.cloud.config.server.prefix
,例如“/ config”,以提供字首下的資源。字首應該開始但不以“/”結尾。它應用於Config Server中的@RequestMappings
(即Spring Boot字首server.servletPath
和server.contextPath
)之下。
如果您想直接從後端儲存庫(而不是從配置伺服器)讀取應用程式的配置,這基本上是一個沒有端點的嵌入式配置伺服器。如果不使用@EnableConfigServer
註釋(只設置spring.cloud.config.server.bootstrap=true
),則可以完全關閉端點。
推送通知和Spring Cloud Bus
許多原始碼儲存庫提供程式(例如Github,Gitlab或Bitbucket)將通過webhook通知您儲存庫中的更改。您可以通過提供商的使用者介面將webhook配置為URL和一組感興趣的事件。例如, Github 將使用包含提交列表的JSON主體和“X-Github-Event”等於“push”的標頭檔案傳送到webhook。如果您在spring-cloud-config-monitor
庫中新增依賴關係並激活配置伺服器中的Spring Cloud Bus,則啟用“/ monitor”端點。
當Webhook被啟用時,配置伺服器將傳送一個RefreshRemoteApplicationEvent
針對他認為可能已經改變的應用程式。變更檢測可以進行策略化,但預設情況下,它只是查詢與應用程式名稱匹配的檔案的更改(例如,“foo.properties”針對的是“foo”應用程式,“application.properties”針對所有應用程式) 。如果要覆蓋該行為的策略是PropertyPathNotificationExtractor
,它接受請求標頭和正文作為引數,並返回更改的檔案路徑列表。
預設配置與Github,Gitlab或Bitbucket配合使用。除了Github,Gitlab或Bitbucket的JSON通知之外,您還可以通過使用表單編碼的身體引數path={name}
通過POST為“/ monitor”來觸發更改通知。這將廣播到匹配“{name}”模式的應用程式(可以包含萬用字元)。
注意 |
只有在配置伺服器和客戶端應用程式中啟用spring-cloud-bus 時才會傳送RefreshRemoteApplicationEvent 。 |
注意 |
預設配置還檢測本地git儲存庫中的檔案系統更改(在這種情況下不使用webhook,但是一旦編輯配置檔案,將會播放重新整理)。 |
Spring Cloud Config客戶端
一個Spring Boot應用程式可以立即利用Spring Config Server(或應用程式開發人員提供的其他外部屬性源),並且還將獲取與Environment
更改事件相關的一些其他有用功能。
配置第一引導
這是在類路徑中具有Spring Cloud Config Client的任何應用程式的預設行為。當配置客戶端啟動時,它將通過配置伺服器(通過引導配置屬性spring.cloud.config.uri
)繫結並使用遠端屬性源初始化Spring Environment
。
這樣做的最終結果是所有想要使用配置伺服器的客戶端應用程式都需要spring.cloud.config.uri
(預設為“http:// localhost:8888”)的bootstrap.yml
(或環境變數) )。
發現第一個引導
如果您正在使用“DiscoveryClient”實現,例如Spring Cloud Netflix和Eureka Service Discovery或Spring Cloud Consul(Spring Cloud Zookeeper還不支援此功能),那麼您可以讓Config Server註冊Discovery Discovery,但在預設的“配置優先”模式下,客戶端將無法利用註冊。
如果您希望使用DiscoveryClient
找到Config Server,可以通過設定spring.cloud.config.discovery.enabled=true
(預設為“false”)來實現。最終的結果是客戶端應用程式都需要具有適當的發現配置的bootstrap.yml
(或環境變數)。例如,使用Spring Cloud Netflix,您需要定義Eureka伺服器地址,例如eureka.client.serviceUrl.defaultZone
。使用此選項的價格是啟動時額外的網路往返,以定位服務註冊。好處是配置伺服器可以更改其座標,只要發現服務是一個固定點。預設的服務標識是“configserver”,但是您可以使用spring.cloud.config.discovery.serviceId
在客戶端上進行更改(在伺服器上可以通過設定spring.application.name
以通常方式更改服務。
發現客戶端實現都支援某種元資料對映(例如,對於Eureka,我們有eureka.instance.metadataMap
)。可能需要在其服務註冊元資料中配置Config Server的一些其他屬性,以便客戶端可以正確連線。如果使用HTTP Basic安全配置伺服器,則可以將憑據配置為“使用者名稱”和“密碼”。並且如果配置伺服器具有上下文路徑,您可以設定“configPath”。例如,對於作為Eureka客戶端的配置伺服器:
bootstrap.yml
eureka:
instance:
...
metadataMap:
user: osufhalskjrtl
password: lviuhlszvaorhvlo5847
configPath: /config
配置客戶端快速失敗
在某些情況下,如果服務無法連線到配置伺服器,則可能希望啟動服務失敗。如果這是所需的行為,請設定引導配置屬性spring.cloud.config.failFast=true
,客戶端將以異常停止。
配置客戶端重試
如果您希望配置伺服器在您的應用程式啟動時可能偶爾不可用,您可以要求它在發生故障後繼續嘗試。首先,您需要設定spring.cloud.config.failFast=true
,然後您需要將spring-retry
和spring-boot-starter-aop
新增到您的類路徑中。預設行為是重試6次,初始退避間隔為1000ms,指數乘數為1.1,用於後續退避。您可以使用spring.cloud.config.retry.*
配置屬性配置這些屬性(和其他)。
提示 |
要完全控制重試,請使用id“configServerRetryInterceptor”新增RetryOperationsInterceptor 型別的@Bean 。Spring Retry有一個RetryInterceptorBuilder ,可以輕鬆建立一個。 |
查詢遠端配置資源
配置服務從/{name}/{profile}/{label}
提供屬性源,客戶端應用程式中的預設繫結
-
“name”=
${spring.application.name}
-
“profile”=
${spring.profiles.active}
(實際上是Environment.getActiveProfiles()
) -
“label”=“master”
所有這些都可以通過設定spring.cloud.config.*
(其中*
是“name”,“profile”或“label”)來覆蓋。“標籤”可用於回滾到以前版本的配置; 使用預設的Config Server實現,它可以是git標籤,分支名稱或提交ID。標籤也可以以逗號分隔的列表形式提供,在這種情況下,列表中的專案會逐個嘗試,直到成功。例如,當您可能希望將配置標籤與您的分支對齊,但使其成為可選(例如spring.cloud.config.label=myfeature,develop
)時,這對於在特徵分支上工作時可能很有用。
安全
如果您在伺服器上使用HTTP基本安全性,那麼客戶端只需要知道密碼(如果不是預設使用者名稱)。您可以通過配置伺服器URI,或通過單獨的使用者名稱和密碼屬性,例如
bootstrap.yml
spring:
cloud:
config:
uri: https://user:[email protected]
要麼
bootstrap.yml
spring:
cloud:
config:
uri: https://myconfig.mycompany.com
username: user
password: secret
spring.cloud.config.password
和spring.cloud.config.username
值覆蓋URI中提供的任何內容。
如果您在Cloud Foundry部署應用程式,則提供密碼的最佳方式是通過服務憑證(例如URI),因為它甚至不需要在配置檔案中。在Cloud Foundry上為本地工作的使用者提供的服務的一個例子,名為“configserver”:
bootstrap.yml
spring:
cloud:
config:
uri: ${vcap.services.configserver.credentials.uri:http://user:[email protected]:8888}
如果您使用另一種形式的安全性,則可能需要向ConfigServicePropertySourceLocator
提供RestTemplate
(例如,通過在引導上下文中獲取它並注入一個)。ConfigServicePropertySourceLocator
提供{249 /}(例如通過在引導上下文中獲取它並注入)。
健康指標
配置客戶端提供嘗試從配置伺服器載入配置的Spring Boot執行狀況指示器。可以通過設定health.config.enabled=false
來禁用執行狀況指示器。由於效能原因,響應也被快取。預設快取生存時間為5分鐘。要更改該值,請設定health.config.time-to-live
屬性(以毫秒為單位)。
提供自定義RestTemplate
在某些情況下,您可能需要從客戶端自定義對配置伺服器的請求。通常這涉及傳遞特殊的Authorization
標頭來對伺服器的請求進行身份驗證。要提供自定義RestTemplate
,請按照以下步驟操作。
-
設定
spring.cloud.config.enabled=false
以禁用現有的配置伺服器屬性源。 -
使用
PropertySourceLocator
的實現建立一個新的配置bean。
CustomConfigServiceBootstrapConfiguration.java
@Configuration
public class CustomConfigServiceBootstrapConfiguration {
@Bean
public ConfigClientProperties configClientProperties() {
ConfigClientProperties client = new ConfigClientProperties(this.environment);
client.setEnabled(false);
return client;
}
@Bean
public ConfigServicePropertySourceLocator configServicePropertySourceLocator() {
ConfigClientProperties clientProperties = configClientProperties();
ConfigServicePropertySourceLocator configServicePropertySourceLocator = new ConfigServicePropertySourceLocator(clientProperties);
configServicePropertySourceLocator.setRestTemplate(customRestTemplate(clientProperties));
return configServicePropertySourceLocator;
}
}
-
在
resources/META-INF
中建立一個名為spring.factories
的檔案,並指定您的自定義配置。
spring.factorties
org.springframework.cloud.bootstrap.BootstrapConfiguration = com.my.config.client.CustomConfigServiceBootstrapConfiguration
Vault
當使用Vault作為配置伺服器的後端時,客戶端將需要為伺服器提供令牌以從Vault中檢索值。可以通過在bootstrap.yml
中設定spring.cloud.config.token
來在客戶端中提供此令牌。
bootstrap.yml
spring:
cloud:
config:
token: YourVaultToken
Vault
巢狀金鑰在Vault
Vault支援將鍵嵌入儲存在Vault中的值。例如
echo -n '{"appA": {"secret": "appAsecret"}, "bar": "baz"}' | vault write secret/myapp -
此命令會將JSON物件寫入您的Vault。要在Spring中訪問這些值,您將使用傳統的點(。)註釋。例如
@Value("${appA.secret}")
String name = "World";
上述程式碼將name
變數設定為appAsecret
。