簡介
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。
這個時候,我們可以通過http://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 的結構和使用。如有錯誤,歡迎指正。
最後,感謝閱讀。
參考資料
本文為原創文章,轉載請附上原文出處連結:https://www.cnblogs.com/ZhangZiSheng001/p/14918588.html