1 Spring Boot Externalized Configuration
仔細(xì)閱讀 Spring Boot 源代碼會(huì)發(fā)現(xiàn),Spring boot application 啟動(dòng)時(shí)會(huì)依次在四個(gè)路徑尋找配置文件:
在:
- file:config/ 當(dāng)前文件路徑下的 config 目錄
- file: 當(dāng)前文件路徑
- classpath:/config/ 類(lèi)路徑下的 config 目錄
- classpath:/ 類(lèi)路徑
第一次逐目錄遍歷尋找尋找如下文件:
- bootstrap.properties
- bootstrap.xml
- bootstrap.yml
- bootstrap.yaml
第二次遍歷尋找如下文件(未指定 active profile 時(shí)):
- bootstrap-default.properties
- bootstrap-default.xml
- bootstrap-default.yml
- bootstrap-default.yaml
第三次遍歷尋找如下文件
- application.properties
- application.xml
- application.yml
- application.yaml
第四次遍歷尋找如下文件(未指定 active profile 時(shí))
- application-default.properties
- application-default.xml
- application-default.yml
- application-default.yaml
舉兩個(gè)??
- spring boot 應(yīng)用啟動(dòng)時(shí)加載的第一個(gè)配置文件是:file:config/bootstrap.properties
- spring boot 應(yīng)用啟動(dòng)時(shí)加載的最后一個(gè)配置文件是:classpath:/application.yaml
條件變量有:
- 目錄(file:config/、file:、classpath:/config/、classpath:/)
- 系列(bootstrap、bootstrap-{profile}、application、application-{profile}系列)
- 后綴(properties、xml、yml、yaml)
- 家族(帶 bootstrap 字樣為 bootstrap 家族,application 亦然)
1.1 同目錄 的 同系列 配置文件,先加載的優(yōu)先級(jí)最高。即 properties 優(yōu)先級(jí)最高,yaml 優(yōu)先級(jí)最低
- Spring Boot 應(yīng)用程序啟動(dòng)的端口是
- 答案:9999
1.2 同系列 的 同后綴 配置文件,先加載的優(yōu)先級(jí)最高。即 file:config/ 目錄優(yōu)先級(jí)最高,classpath:/ 目錄優(yōu)先級(jí)最低
- Spring Boot 應(yīng)用程序啟動(dòng)的端口是
- 答案:10063
1.3 同目錄 的 同后綴 配置文件,后加載的優(yōu)先級(jí)最高。即 application-{profile}.xxx 優(yōu)先級(jí)最高,bootstrap.xxx 優(yōu)先級(jí)最低
- Spring Boot 應(yīng)用程序啟動(dòng)的端口是
- 答案:10002
1.4 Spring Boot 的參數(shù)配置形式 - 驗(yàn)證前面結(jié)論
參考 官網(wǎng)資料
1.5 一點(diǎn)猜想
- bootstrap 家族優(yōu)先級(jí)最高的選手:位于被首先掃描目錄 file:config/ 下的 bootstrap-default.properties
- application 家族優(yōu)先級(jí)最低的選手:位于被最后掃描目錄 classpath:/ 下的 application.yaml
- Spring Boot 應(yīng)用程序啟動(dòng)的端口是
- 答案:10003 bootstrap 家族優(yōu)先級(jí)一定低于 application 家族
1.6 總結(jié)
- bootstrap 系列優(yōu)先級(jí)一定低于 application 系列
- 所在目錄越先被掃描優(yōu)先級(jí)越高
- active profile 文件優(yōu)先級(jí)更高
2 Spring Cloud Config
2.1 沒(méi)有 Spring Cloud Config 的時(shí)候
2.2 使用 Spring Cloud Config 實(shí)現(xiàn)配置文件管理
兩個(gè)特點(diǎn)
- Externalized 外部化,配置文件存放在 jar 包外部
- Centralized 中心化,各種服務(wù)、各種環(huán)境的配置文件都集中放置在一個(gè)地方
2.3 優(yōu)先級(jí)問(wèn)題
根據(jù) Spring Cloud 文檔所述:
By default, bootstrap properties (not bootstrap.properties but properties that are loaded during the bootstrap phase) are added with high precedence, so they cannot be overridden by local configuration.
需要區(qū)分兩個(gè)概念:
- properties that are loaded during the bootstrap phase:bootstrap 階段加載的配置
- bootstrap.properties:bootstrap.properties/yml 文件中指定的配置
2.4 bootstrap.yml 用處
The bootstrap context uses a different convention for locating external configuration than the main application context. Instead of application.yml (or .properties), you can use bootstrap.yml, keeping the external configuration for bootstrap and main context nicely separate.
一個(gè)例子:
spring:
application:
name: foo
cloud:
config:
uri: ${SPRING_CONFIG_URI:http://localhost:8888}
3 經(jīng)驗(yàn)總結(jié)
3.1 同一個(gè)服務(wù)的兩個(gè)實(shí)例主鍵生成重復(fù)
服務(wù)內(nèi)部采用 SnowFlake 算法生成 ID,不同的實(shí)例需配置不同的 machineId 等作為實(shí)例的標(biāo)識(shí)。發(fā)生錯(cuò)誤時(shí)的配置情況如下:
- jar 包內(nèi)部 application.yml 中配置 machineId 參數(shù),不同實(shí)例具有相同配置
- jar 包同目錄下 bootstrap.yml 中配置 machineId 參數(shù),不同實(shí)例配不同的 machineId
我們?cè)酒谕?jar 包同目錄 bootstrap.yml 中的 machineId 參數(shù)配置可以?xún)?yōu)先于 jar 包內(nèi)部 application.yml 中的配置,但是根據(jù) Spring Cloud Config 文檔的說(shuō)明,以及我們自己做的實(shí)驗(yàn),可以看到,bootstrap.yml 在一般參數(shù)中具有低于 application.yml 的優(yōu)先級(jí),所以最終兩個(gè)實(shí)例都讀到了程序內(nèi)部配置的 machineId,造成生成了重復(fù) ID。
由于正式環(huán)境只會(huì)持有一份配置文件,所以無(wú)法將 machineId 放到配置中心,當(dāng)時(shí)采用的解決辦法是將 machineId 配置從 jar 包內(nèi)部抹去,使得應(yīng)用只能從 jar 包外部的 bootstrap.yml 讀取 machineId。但是由于服務(wù)內(nèi)部沒(méi)有了 machineId,導(dǎo)致本地都無(wú)法啟動(dòng)服務(wù)。更好的做法為:在 jar 包旁新建 application.yml 配置文件并配置 machineId 參數(shù),借助頂層目錄的 application.yml 的高優(yōu)先級(jí),覆蓋 jar 包內(nèi)的 machineId 配置