詳解apollo的設計與使用
簡介
apollo 是一款由攜程團隊開發的配置中心,可以實現配置的集中管理、分環境管理、即時生效等等。在這篇博客中,我們可以了解到:
- 為什麼使用配置中心
- 如何設計一個配置中心
- apollo 是如何設計的
- 如何使用 apollo
為什麼使用配置中心
這裡我回答的是為什麼使用配置中心,而不是為什麼使用 apollo。為什麼呢?因為我不建議使用 apollo,之所以研究它,只是好奇而已。另外,為什麼使用配置中心,這個是需求層面的問題,需求是明確的,但實現需求的手段就不一定了。這個有點像人需要吃飯但不一定得吃饅頭。
首先,我們可以想像下,如果沒有配置中心,我們的項目可能是這樣的:不同環境的配置文件都放在項目裏面,部署時可以通過啟動參數來指定使用哪個環境的配置。
這種方式有兩個比較大的缺點:
- 不安全。項目的開發人員可以看到生產環境的各種地址、賬號、密碼等等,這是不安全的;
- 配置更新需要重啟項目才能生效。
配置中心就是為了解決這些問題而存在的。
如何設計一個配置中心
安全
還是繼續上面的分析。為了解決配置的安全問題,我們很自然地會想到把配置文件放到一個開發人員看不到的地方,即項目和配置分離,如圖所示。這個放配置的地方可以是數據庫,可以是遠程文件,也可以是獨立的應用,等等。
這樣就能解決安全問題了嗎?還是不行,項目的開發人員還是能看到生產的配置。為什麼呢?因為測試環境和生產環境共用一個配置中心,開發人員能拿到測試環境的配置,也就能拿到生產環境的配置。所以,環境不同,配置中心也不一樣(如果非要共用一個,得想好隔離方案)。
即時發佈
接着,我們來解決第二個問題:配置的即時發佈。
我們需要在客戶端和配置中心之間建立某種機制,讓客戶端可以感知到配置的變化,一般可以通過以下方式實現(apollo 兩種方式都用了):
- 客戶端定時重拉配置;
- 服務端主動推送。
還有一點需要注意,客戶端拿到新的配置後,需要讓配置生效,即把新配置注入到對應的類中,這一點在集成了 spring 的項目里會好處理一些。
那麼 apollo 是如何實現的呢?我們可以關注下com.ctrip.framework.apollo.spring.property.SpringValueRegistry
這個類,它裏面存放了項目的所有配置信息,客戶端感知到配置變更後,只要更新這上面的配置就行。而這個類裏面的配置是通過BeanDefinitionRegistryPostProcessor
+BeanFactoryPostProcessor
來完成初始化的。原理並不複雜,這裡就不擴展了。
方便管理
另外,為了更方便地管理配置,配置中心一般會有控制台。控制台有兩種形式(apollo 採用第一種):
- 所有環境共用一個控制台(這種情況需要增加一個應用來集成各個環境的配置);
- 不同環境使用不同的控制台。
經過以上的分析,我們設計出了一個簡單的配置中心。
apollo是如何設計的
關於這個問題,官方給出了這樣一張圖。
是不是看不懂呢?其實看不懂很正常,因為作為一個配置中心來說,apollo 太重了。
我們還是繼續上面的分析,在雛形的基礎上慢慢設計出 apollo 的結構。
首先,如果配置中心是單獨的應用,配置信息放在數據庫裏面,它的結構大概是這樣的。
apollo 將這裡的 config server 拆分成了 config service 和 admin service,前者負責與 app001交互,後者負責與 config console 交互。這一步吧,我倒是覺得可有可無。
其實分析到這裡,apollo 作為配置中心的部分已經完整的畫出來了。目前為止,apollo 還算是一個中規中矩的配置中心,但是,apollo 給的東西太多了,它還提供了集群支持,官方給的圖中,meta server、eureka 都屬於這部分。我認為,集群的支持本意是好的,但僅僅為了支持這個功能讓 apollo 變得太過龐大。
那麼,要如何實現集群支持呢?其實有一個最簡單的方案,就是直接通過 SLB 訪問即可。
但是人家 apollo 偏偏要用 eureka,如圖所示。config service 需要先註冊到 eureka server,然後 app001 要先從 eureka server 獲取 config service 的地址,然後再訪問。config console 和 admin service 的交互同理。
走到這裡,無非是採用 SLB 還是採用 eureka 來實現負載均衡,還是可以接受的。
但是呢?使用 eureka 來實現負載均衡的話,就要求 app001 必須引入 eureka client,但我不想引入怎麼辦。於是,apollo 開發團隊又搞出一個新的項目 meta server 來屏蔽對 eureka 的依賴。
我們發現,apollo 已經大得離譜了。
然而還沒完,在上面的結構圖中,我們會發現,meta server 如果掛了,config service 做再多集群也沒用,也就是說 meta server 也需要做集群,這時應該怎麼處理呢?apollo 官方給出了方案–使用 SLB。
那麼,我想問,為什麼不一開始就使用 SLB 呢??
我看了官網關於這個問題的回答,之所以這麼設計是為了避免客戶端和 config service 之間的長連接給 SLB 增加過多的負擔。當然,這種解釋還是可以接受,但是不是有更好的方案呢?
如何使用apollo
測試方案
我把 apollo github 上的代碼拉到本地重新編譯打包,代碼稍有改動。我的測試方案如下。
服務器 1 是我的 windows 電腦,用來模擬 dev 環境,上面部署了配置中心、eureka、數據庫,客戶端和 portal 也部署在這台電腦。
服務器 2 是我的 linux 服務器,用來模擬 pro 環境,上面部署了配置中心、eureka、數據庫。
環境說明
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。
啟動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。
啟動admin service
mvn clean package
打包 admin service 項目,通過批處理文件啟動項目,端口是 8082。在我們的測試例子中,config service 和 admin service 誰先啟動都可以,但是,如果我們使用了 config service 里的 eureka server,那麼必須先啟動 config service。
啟動portal
mvn clean package
打包 portal 項目,通過批處理文件啟動項目,端口是 8083。
這個時候,我們可以通過//127.0.0.1:8083/
訪問管理界面(賬號 apollo,密碼 admin)。我們可以看到實例項目 SampleApp,它的兩個環境分別對應我們服務器 1 和服務器 2 的配置中心。
啟動apollo demo
apollo demo 用來模擬我們的實際項目,演示從配置中心獲取配置,項目中需要引入 apollo-client 的依賴。
mvn clean package
打包項目,通過批處理文件啟動項目(連接的是 dev 的配置中心,可以自行修改)。當我們輸入 key 為 timeout 時,可以拿到配置中心的 value 為 100。
走到這裡,我們成功地完成了 apollo 的部署。
以上基本講完了 apollo 的結構和使用。如有錯誤,歡迎指正。
最後,感謝閱讀。
參考資料
本文為原創文章,轉載請附上原文出處鏈接://www.cnblogs.com/ZhangZiSheng001/p/14918588.html