簡介
apollo 是一款由攜程團隊開發的配置中心,可以實現配置的集中管理、分環境管理、即時生效等等。在這篇部落格中,我們可以瞭解到:
- 為什麼使用配置中心
- 如何設計一個配置中心
- apollo 是如何設計的
- 如何使用 apollo
為什麼使用配置中心
這裡我回答的是為什麼使用配置中心,而不是為什麼使用 apollo。為什麼呢?因為我不建議使用 apollo,之所以研究它,只是好奇而已。另外,為什麼使用配置中心,這個是需求層面的問題,需求是明確的,但實現需求的手段就不一定了。這個有點像人需要吃飯但不一定得吃饅頭。
首先,我們可以想象下,如果沒有配置中心,我們的專案可能是這樣的:不同環境的配置檔案都放在專案裡面,部署時可以通過啟動引數來指定使用哪個環境的配置。
![zzs_apollo_01](https://i.iter01.com/images/cbcf62473b37e6fc32b16319bead2594000a1c1ce55d2f9ed0d52003959d1e46.png)
這種方式有兩個比較大的缺點:
- 不安全。專案的開發人員可以看到生產環境的各種地址、賬號、密碼等等,這是不安全的;
- 配置更新需要重啟專案才能生效。
配置中心就是為了解決這些問題而存在的。
如何設計一個配置中心
安全
還是繼續上面的分析。為了解決配置的安全問題,我們很自然地會想到把配置檔案放到一個開發人員看不到的地方,即專案和配置分離,如圖所示。這個放配置的地方可以是資料庫,可以是遠端檔案,也可以是獨立的應用,等等。
![zzs_apollo_02](https://i.iter01.com/images/7dd953ab02c0ca94dee5d6b5b95d39f6b721d40922922b18da402150cb235b7c.png)
這樣就能解決安全問題了嗎?還是不行,專案的開發人員還是能看到生產的配置。為什麼呢?因為測試環境和生產環境共用一個配置中心,開發人員能拿到測試環境的配置,也就能拿到生產環境的配置。所以,環境不同,配置中心也不一樣(如果非要共用一個,得想好隔離方案)。
![zzs_apollo_03](https://i.iter01.com/images/98787d35e27cf58ad1e7e2595ccf29a23df0630bf4aa98f80b6f3b0e4395b676.png)
即時釋出
接著,我們來解決第二個問題:配置的即時釋出。
我們需要在客戶端和配置中心之間建立某種機制,讓客戶端可以感知到配置的變化,一般可以通過以下方式實現(apollo 兩種方式都用了):
- 客戶端定時重拉配置;
- 服務端主動推送。
還有一點需要注意,客戶端拿到新的配置後,需要讓配置生效,即把新配置注入到對應的類中,這一點在整合了 spring 的專案裡會好處理一些。
那麼 apollo 是如何實現的呢?我們可以關注下com.ctrip.framework.apollo.spring.property.SpringValueRegistry
這個類,它裡面存放了專案的所有配置資訊,客戶端感知到配置變更後,只要更新這上面的配置就行。而這個類裡面的配置是通過BeanDefinitionRegistryPostProcessor
+BeanFactoryPostProcessor
來完成初始化的。原理並不複雜,這裡就不擴充套件了。
方便管理
另外,為了更方便地管理配置,配置中心一般會有控制檯。控制檯有兩種形式(apollo 採用第一種):
- 所有環境共用一個控制檯(這種情況需要增加一個應用來整合各個環境的配置);
- 不同環境使用不同的控制檯。
![zzs_apollo_04](https://i.iter01.com/images/e1697e90166a350ff65e27b78803ef21087b5ab52dfcf416b358dfd998fe95ff.png)
經過以上的分析,我們設計出了一個簡單的配置中心。
apollo是如何設計的
關於這個問題,官方給出了這樣一張圖。
![zzs_apollo_05](https://i.iter01.com/images/710831a181359beeeedb2651a0600ec2f538db1bd610627ed03a10c5c08d921f.png)
是不是看不懂呢?其實看不懂很正常,因為作為一個配置中心來說,apollo 太重了。
我們還是繼續上面的分析,在雛形的基礎上慢慢設計出 apollo 的結構。
首先,如果配置中心是單獨的應用,配置資訊放在資料庫裡面,它的結構大概是這樣的。
![zzs_apollo_06](https://i.iter01.com/images/ec54c20996c800873e524cb99d9beb1115f3e9d973c39049cc1cbc58d31123d8.png)
apollo 將這裡的 config server 拆分成了 config service 和 admin service,前者負責與 app001互動,後者負責與 config console 互動。這一步吧,我倒是覺得可有可無。
![zzs_apollo_07](https://i.iter01.com/images/0d64b7530e1173e03066dc14c8b141692f8199ef3c5373effc68f8ec7dbff1df.png)
其實分析到這裡,apollo 作為配置中心的部分已經完整的畫出來了。目前為止,apollo 還算是一箇中規中矩的配置中心,但是,apollo 給的東西太多了,它還提供了叢集支援,官方給的圖中,meta server、eureka 都屬於這部分。我認為,叢集的支援本意是好的,但僅僅為了支援這個功能讓 apollo 變得太過龐大。
那麼,要如何實現叢集支援呢?其實有一個最簡單的方案,就是直接通過 SLB 訪問即可。
![zzs_apollo_08](https://i.iter01.com/images/04a0ead4c6755efdb421b3f354836b66271914e330f713a2d4dc001af6889310.png)
但是人家 apollo 偏偏要用 eureka,如圖所示。config service 需要先註冊到 eureka server,然後 app001 要先從 eureka server 獲取 config service 的地址,然後再訪問。config console 和 admin service 的互動同理。
![zzs_apollo_09](https://i.iter01.com/images/ace38c3e377d823b324472c399483c7823d58b2d7353367f17898f93dbf43816.png)
走到這裡,無非是採用 SLB 還是採用 eureka 來實現負載均衡,還是可以接受的。
但是呢?使用 eureka 來實現負載均衡的話,就要求 app001 必須引入 eureka client,但我不想引入怎麼辦。於是,apollo 開發團隊又搞出一個新的專案 meta server 來遮蔽對 eureka 的依賴。
![zzs_apollo_10](https://i.iter01.com/images/aa508c12cbe917c0062c4ccfba6b92756afa0683559d90a6381e755fb62450a0.png)
我們發現,apollo 已經大得離譜了。
然而還沒完,在上面的結構圖中,我們會發現,meta server 如果掛了,config service 做再多叢集也沒用,也就是說 meta server 也需要做叢集,這時應該怎麼處理呢?apollo 官方給出了方案--使用 SLB。
那麼,我想問,為什麼不一開始就使用 SLB 呢??
我看了官閘道器於這個問題的回答,之所以這麼設計是為了避免客戶端和 config service 之間的長連線給 SLB 增加過多的負擔。當然,這種解釋還是可以接受,但是不是有更好的方案呢?
![zzs_apollo_12](https://i.iter01.com/images/17a10ac6ed10f46e48137f57cf496cda6cb65672ad2453ef75cbd7bedab90ea5.png)
如何使用apollo
測試方案
我把 apollo github 上的程式碼拉到本地重新編譯打包,程式碼稍有改動。我的測試方案如下。
伺服器 1 是我的 windows 電腦,用來模擬 dev 環境,上面部署了配置中心、eureka、資料庫,客戶端和 portal 也部署在這臺電腦。
伺服器 2 是我的 linux 伺服器,用來模擬 pro 環境,上面部署了配置中心、eureka、資料庫。
![zzs_apollo_11](https://i.iter01.com/images/b3210a2bd318789ed337ee71a3b5b6b5409383c05d9cef083f879e2c3a18959b.png)
環境說明
os:伺服器1:win 10,伺服器2:linux
eureka:1.10.11
apollo:1.8.0
maven:3.6.3
jdk:1.8.0_231
mysql:5.7.28
建立資料庫
在伺服器 1 和伺服器 2 新建資料庫ApolloPortalDB
和ApolloConfigDB
,具體指令碼為apollo sql。
![zzs_apollo_13](https://i.iter01.com/images/42cff65a95ef60ffb6be954c488e57d513cd9e220948589343f626376c8cc227.png)
啟動eureka
config service 中自帶了一個 eureka server,但我不打算用,所以後面的測試中都會將它禁用掉。這裡分別啟動伺服器 1 和伺服器 2 的 eureka,埠為 8080。eureka 相關內容可以參考我的另一篇部落格:Java原始碼詳解系列(十二)--Eureka的使用和原始碼。
啟動config service和meta server
mvn clean package
打包 config service 專案,通過批處理檔案啟動專案(根據作業系統選擇不同的指令碼),埠是 8081。config service 裡面整合了 meta server,所以,這裡我們同時啟動了 config service 和 meta server。
![zzs_apollo_14](https://i.iter01.com/images/f4448defa946654c97b41ab93cd9484ab4cdeac65dd8a89b0c51ce57cab3a088.png)
啟動admin service
mvn clean package
打包 admin service 專案,通過批處理檔案啟動專案,埠是 8082。在我們的測試例子中,config service 和 admin service 誰先啟動都可以,但是,如果我們使用了 config service 裡的 eureka server,那麼必須先啟動 config service。
![zzs_apollo_15](https://i.iter01.com/images/d52fd97a05895c903aa8ce3810205d49cf142a06ef7c5aa89e04fba71f22e0c5.png)
啟動portal
mvn clean package
打包 portal 專案,通過批處理檔案啟動專案,埠是 8083。
![zzs_apollo_16](https://i.iter01.com/images/dc693ebe460db340e83a59a82c71b149d517fa7844f40be9522f763db6cdc8f3.png)
這個時候,我們可以通過http://127.0.0.1:8083/
訪問管理介面(賬號 apollo,密碼 admin)。我們可以看到例項專案 SampleApp,它的兩個環境分別對應我們伺服器 1 和伺服器 2 的配置中心。
![zzs_apollo_17](https://i.iter01.com/images/3f620a75dd39073304d8907107e125184d07acf0062e54e6c25adafa914a15bb.png)
啟動apollo demo
apollo demo 用來模擬我們的實際專案,演示從配置中心獲取配置,專案中需要引入 apollo-client 的依賴。
mvn clean package
打包專案,通過批處理檔案啟動專案(連線的是 dev 的配置中心,可以自行修改)。當我們輸入 key 為 timeout 時,可以拿到配置中心的 value 為 100。
![zzs_apollo_18](https://i.iter01.com/images/fcf4e641fdc63216cedf278427868031791d463c789630c4ffc87130b0f19ac8.png)
走到這裡,我們成功地完成了 apollo 的部署。
以上基本講完了 apollo 的結構和使用。如有錯誤,歡迎指正。
最後,感謝閱讀。
參考資料
本文為原創文章,轉載請附上原文出處連結:https://www.cnblogs.com/ZhangZiSheng001/p/14918588.html