Spring Cloud Config 伺服器(上)
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倉庫。
注意 | 在Windows中,如果檔案URL為絕對驅動器字首,例如file:///${user.home}/config-repo,則需要額外的“/”。 |
---|
提示 | 以下是上面示例中建立git倉庫的方法: |
---|
$ cd $HOME
$ mkdir config-repo
$ cd config-repo
$ git init .
$ echo info.foo: bar > application.properties
$ git add -A .
$ git commit -m "Add application.properties"
警告 | 使用本地檔案系統進行git儲存庫僅用於測試。使用伺服器在生產環境中託管配置庫。 |
---|
警告 | 如果您只保留文字檔案,則配置庫的初始克隆將會快速有效。如果您開始儲存二進位制檔案,尤其是較大的檔案,則可能會遇到伺服器中第一個配置請求和/或記憶體不足錯誤的延遲。 |
---|
環境庫
您要在哪裡儲存配置伺服器的配置資料?管理此行為的策略是EnvironmentRepository,服務於Environment物件。此Environment是Spring Environment(包括propertySources作為主要功能)的域的淺層副本。Environment資源由三個變數引數化:
-
{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]:配置/雲配置”。必須在~/.ssh/known_hosts檔案中存在Git伺服器的條目,並且它是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 --globalhttp.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-。一些作業系統會定期清除臨時目錄。這可能會導致意外的行為,例如缺少屬性。為避免此問題,請通過將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中的絕對路徑需要額外的“/”,例如file:///${user.home}/config-repo |
---|
警告 | 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。
名稱 | 預設值 |
---|---|
host | 127.0.0.1 |
port | 8200 |
scheme | HTTP |
backend | 祕密 |
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請求傳送給您的配置伺服器以檢索值。
在提出上述要求後,您應該會看到類似的回覆。
{
"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"
}
}
]
}
多個Properties來源
使用Vault時,您可以為應用程式提供多個屬性源。例如,假設您已將資料寫入Vault中的以下路徑。
secret/myApp,dev
secret/myApp
secret/application,dev
secret/application
寫入secret/application的Properties可 用於使用配置伺服器的所有應用程式。名稱為myApp的應用程式將具有寫入secret/myApp和secret/application的任何屬性。當myApp啟用dev配置檔案時,寫入所有上述路徑的屬性將可用,列表中第一個路徑中的屬性優先於其他路徑。
與所有應用共享配置
基於檔案的儲存庫
使用基於檔案(即git,svn和native)的儲存庫,檔名為application*的資源在所有客戶端應用程式(所以application.properties,application.yml,application-*.properties等)之間共享)。您可以使用這些檔名的資源來配置全域性預設值,並根據需要將其覆蓋應用程式特定的檔案。
#_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將被賦予最低優先順序。
屬性覆蓋
配置伺服器具有“覆蓋”功能,允許操作員為應用程式使用普通的Spring Boot鉤子不會意外更改的所有應用程式提供配置屬性。要宣告覆蓋,只需將名稱/值對的地圖新增到spring.cloud.config.server.overrides。例如
spring:
cloud:
config:
server:
overrides:
foo: bar
將導致配置客戶端的所有應用程式獨立於自己的配置讀取foo=bar。(當然,應用程式可以以任何方式使用Config Server中的資料,因此覆蓋不可強制執行,但如果它們是Spring Cloud Config客戶端,則它們確實提供有用的預設行為。)
提示 | 通過使用反斜槓(“\”)來轉義“$”或“{”,例如${app.foo:bar}解析,可以轉義正常的Spring具有“$ {}”的環境佔位符到“bar”,除非應用程式提供自己的“app.foo”。請注意,在YAML中,您不需要轉義反斜槓本身,而是在您執行的屬性檔案中配置伺服器上的覆蓋。 |
---|
您可以通過在遠端儲存庫中設定標誌spring.cloud.config.overrideNone=true(預設為false),將客戶端中所有覆蓋的優先順序更改為更為預設值,允許應用程式在環境變數或系統屬性中提供自己的值。
歡迎關注作者的公眾號《Java程式設計生活》,每日記載Java程式猿工作中遇到的問題