摘要:對於一個合格的CloudNative應用,應該把本身的程序當作開源軟件來編寫的,不應將數據庫鏈接信息和密碼放在代碼裏,必定要將配置外置。
本文分享自華爲雲社區《[CloudNative] 企業應用上雲實踐手記-Cloud Native Phase 3 - 雲原生應用AutoConfig》,做者:關耳山石html
對於一個合格的CloudNative應用,應該把本身的程序當作開源軟件來編寫的,不應將數據庫鏈接信息和密碼放在代碼裏,必定要將配置外置。java
所以我試着在華爲雲上落地這套標準,期間嘗試了從ServiceStage、CCE、CSE這三個入口進行配置注入,最終實現可以在應用啓動時,主動拉取配置,覆蓋本地配置文件裏的調試配置,並可以在線配置並生效。git
打法是:CCE配置啓動參數,制定SpringProfiles;配合CSE作應用配置,將資源外置後的配置記錄於此,並能夠動態更新,最終實現了配置外置的訴求。github
另外,經過此次增長的多版本管理,嘗試梳理了一下ServiceStage的組件、CCE的workload、CSE的應用和微服務之間,錯綜複雜的概念之間的關係,我的淺見,歡迎指正:spring
1. 初始化配置
在系統初始化的時候,不可能一點配置都沒有,因此保留一些基礎配置在配置文件裏是有必要的。配置外置並不意味着100%的配置都要外置,而是把外部依賴資源的配置,特別是容易變化配置外置。數據庫
1.1 啓用Bootstrap和Spring profile
在代碼層面,首先要進行基礎配置。先看代碼結構,這裏除了最基本的application.yaml,增長了bootstrap.yaml和*-dev.yml等帶後綴的文件。bootstrap
介紹一下原理:緩存
- 首先介紹Bootstrap Application Context:
它是Spring Cloud Context的父Context,因此從外部配置源里加載配置通常從這裏來,且優先級高於其餘一切配置文件。因而,咱們也利用這個能力,藉助CSE的微服務配置中心能力,進行Spring的外部參數寫入。
- 而後介紹Spring profiles:
爲了把通用配置和環境相關的配置區分開,好比DEV環境沒有AK/SK認證,而線上環境都有認證,這種配置項上的區別,引入了Spring profiles的概念,當Springboot啓動的時候,會根據profiles.active參數判斷應該啓用那個環境配置
PS:參考SpringCloud官方解釋app
另外,就是哪些配置應該放在配置文件裏,理論上除了最基礎的配置,在啓動時使用的,其他的配置均可以放在CSE的微服務配置中內心,而沒必要在本地配置文件裏存在,另外就是本地配置裏存在的,也能夠經過二次設置在微服務的配置中內心,進行覆蓋,好比數據庫鏈接池的大小,而不須要修改代碼,至於改完之後,要不要重啓,那就得看生效的邏輯了。分佈式
1.2 引入CSE配置中心
CSE配置中心引入,須要先引入依賴包,而後在bootstrap.yaml中配置CSE配置中心的地址、認證信息等。
這裏能夠參考官方文檔,主要關注bootstrap.yaml的配置參數: 使用分佈式配置中心
補充:獲取spring-cloud-starter-huawei-config的版本
參考地址:huaweicloud/spring-cloud-huawei
能夠參考現有的SpringCloud基線版本,選擇SpringCloud-Huawei的版本
補充:關於配置中心的優先級
微服務引擎提供了分層次的配置機制。按照優先級從高到低,分爲:
- 配置中心(動態配置)
- Java System Property(-D參數)
- 環境變量
- 配置文件
參考官方文檔:配置微服務
2. 本地CSE配置中心能力驗證
前提條件,本地得安裝一個Local-CSE並啓動, 這部分參考雲上DevOps:2.1-本地環境準備
2.1 配置application.yaml和bootstrap.yml
原始文件能夠參考Github的Demo, 配置文件入口, 我這裏進行了修改,由於bootstrap.yaml優先級高於application.yaml,參數只要在bootstrap.yaml中出現過,就不會使用application.yaml中的配置了。
上代碼,application.yaml,能夠看到配置不多,由於大部分bootstrap.yml中已經包含,就都去掉了
這是bootstrap.yml,注意這裏的spring.application.name、spring.cloud.servicecomb.discovery.appName和spring.cloud.servicecomb.discovery.version會組成一個微服務私有的參數做用域,這裏的優先級高於全局做用域application。特別注意,雲上的CSE環境,除了上面提到的,還須要增長server.env參數。另外,server.env有四個參數能夠選development、testing、acceptance、production
關於如上參數的定義, 參考官方文檔:使用分佈式註冊中心和官方文檔:使用分佈式配置中心。
2.2 準備驗證代碼
直接上代碼
2.3 靜態配置能力
爲了驗證CSE配置中心的參數,是否能覆蓋application.yaml中的參數配置,我選了一個很特別的參數:spring.datasource.password,若是可以覆蓋成功,那麼啓動後,建立數據庫鏈接池必定會報錯。
- 首先,打開本地CSE配置中心,地址爲:http://localhost:30106/#/cse/services/config,建立一個配置項,做用域選VodMgrService@CabgOne#1.0.0,關於application的做用域後面再解釋。
- 重啓本地微服務,啓動後建立數據庫鏈接池就報錯了,符合預期。
結論:CSE配置中心的參數,可以覆蓋application.yaml中的參數配置
2.4 動態配置能力
爲了驗證CSE配置中心的參數動態生效,須要使用註解@RefreshScope,同時也引入ConfigRefreshEvent來監聽事件變化,這樣就會獲得一個效果,對於動態生效的參數,可能須要一些重建或刷新,好比鏈接池、緩存、Client等。
- 首先,增長一個配置項config.value
- 而後很快能夠看到後臺日誌打印出來,包括本身的監聽器,也響應了日誌
- 查看一下數據,已經響應爲TryMe
- 具體的配置,在後臺是輪詢的,響應週期配置參數爲cloud.servicecomb.config.watch.delay,目前是10秒一次
- 修改一下配置,爲TryMeAgain
- 再看後臺日誌,有新的觸發器發生
- 再次請求API,數據已經更新
- 再深刻去看,這裏的getChange()返回是一個Set<String>,所以能夠針對特定的參數作文章。
結論:本地CSE配置中心的參數可以動態刷新,並開放了ConfigRefreshEvent,以擴展配置更新後的業務動做。
2.5 配置的做用域限制
目前CSE的配置中心提供兩級做用域限制,一個是全域,一個是私域,即微服務內部(不一樣版本有區分)。
- 增長一個做用域爲application的全域參數,一個做用域爲VodMgrService@CabgOne#1.0.0的私域同名參數
- 驗證一下,生效的做用域是VodMgrService@CabgOne#1.0.0
- 刪除私域參數後,生效的做用域是application
結論:本地CSE配置中心的全域配置的優先級,低於微服務內部配置,即私域配置能夠覆蓋全域配置。
3. 雲上配合外置落地
3.1 代碼提交併自動打包推送SWR
代碼提交,推送到CodeHub上,流水線在CloudPipeline自動驅動起來,開始執行,打包、製做鏡像、推送SWR,而且展開了代碼質量檢查。 這些得益於前面的WIKI:Phase2 - 雲上DevOps
3.2 CCE啓動參數配置
因爲ServiceStage的自動部署能力還不知足,因此手工將DockerImage升級到環境上,這裏直接使用CCE進行操做,緣由在題記裏介紹了,ServiceStage的參數配置不太好用
3.2.1 利用CCE的容器啓動命令寫入參數
- 選擇升級版本,點高級配置,CCE的核心配置入口都在這裏了
- 在啓動時,注入最核心的一個參數-Dspring.profiles.active=uat
- 此處的命令是Docker啓動是的ENTRYPOINT,下面那個是CMD,會覆蓋Dockerfile裏的命令
- 點擊右下角的提交,會看到實例列表中已經有一個新的pod在啓動
- 回到AOM服務,查看日誌,會發現The following profiles are active: uat,符合預期
3.3 CCE環境變量配置
3.3.1 利用CCE的環境變量寫入參數
- 首先回退上面那一步的配置,進入高級設置->環境變量
- 增長環境變量JAVA_TOOL_OPTIONS,值設置爲-Dspring.profiles.active=uat
- 提交之後查看日誌,符合預期
至於爲啥JAVA_TOOL_OPTIONS能用,由於JVM原生就包含這個參數,能夠用來在啓動時寫入配置,能夠參考Oracle的官方文檔
3.4 CCE配置中心
3.4.1 利用CCE的配置中心 + 環境變量寫入參數
CCE的配置中心包含了兩個大類,配置項ConfigMap和祕鑰Secret,前面介紹的CCE環境變量,支持從配置中心導入參數,好比我能夠在ConfigMap裏寫入這個參數,而後在CCE的環境變量中引入。
- 首先建立一個配置項,這裏的配置項是按照集羣、命名空間區分的
- 而後建立一套配置項,輸入一套KV
- 回到CCE升級的步驟,修改環境變量,增長一項配置項寫入的變量,能夠選到剛纔輸入的KEY,就不用輸入VALUE了
而後再看看祕鑰,玩兒法相似,可是有一點很「有趣」:這裏的祕鑰是要主動用BASE64轉碼過才能保存,不過在使用的時候,會解密的,所以沒必要關心轉碼回來的問題。
3.4.2 利用CCE的配置中心 + 數據存儲寫入參數
不管是配置項ConfigMap仍是祕鑰Secret,均可以支持利用CCE的數據存儲掛載能力寫入參數到容器裏,簡單理解,就是會自動幫你把配置下載到一個容器的存儲位置上,文件名是KEY,內容是VALUE,能夠在代碼裏讀取這個配置。
配置方式很簡單,選擇配置項,而後寫一個掛載目錄便可
3.5 雲上CSE配置中心
這裏是另外一個核心,線下驗證過,雲上的CSE相似,可是配置模型更復雜,增長了server.env維度,而且全域和私域參數配置位置不同。
- 首先,從ServiceStage->微服務CSE->配置管理,進入全域配置頁面,選擇環境爲yaml裏配置的server.env參數
返回結果爲,生效
PS:若是這裏不選環境,則參數沒法讀取,即環境爲空也是一類環境,不一樣環境之間隔離
- 而後,從ServiceStage->微服務CSE->微服務目錄,進入私域頁面
進而選擇動態配置,在配置做用域時,選擇不帶version的,環境是固定值,
返回結果爲,生效
- 一樣的頁面下,在配置做用域時,選擇帶version的,
返回結果爲,生效
總結:雲上CSE配置中心參數加載優先級
- P1:微服務私域,帶Version
- P2:微服務私域,無Version
- P3:全域,帶環境
其他參數都不生效,包括全域無環境、全域不一樣環境、微服務私域不一樣Version
總結
綜上,基於華爲雲ServiceStage、CCE、CSE的配置外置能力,能夠支撐微服務在不一樣環境中靈活部署,而無需修改代碼。目前的總結打法是:
- 利用CCE的容器啓動參數,或環境變量,寫入profiles.active參數
- 利用CSE的配置中心,寫入業務參數,如MySQL鏈接串、鏈接池配置、GES引擎地址、VOD服務Endpoint地址等