Apollo(阿波羅)是攜程框架部門研發(fā)的分布式配置中心痢法,能夠集中化管理應用不同環(huán)境、不同集群的配置杜顺,配置修改后能夠實時推送到應用端财搁,并且具備規(guī)范的權限、流程治理等特性躬络,適用于微服務配置管理場景尖奔。
服務端架構
上圖簡要描述了 Apollo 的總體設計:
- Config Service 提供配置的讀取、推送等功能洗鸵,服務對象是 Apollo 客戶端
- Admin Service 提供配置的修改越锈、發(fā)布等功能仗嗦,服務對象是 Apollo Portal(管理界面)
- Config Service 和 Admin Service 在生產環(huán)境都是多實例膘滨、無狀態(tài)部署碌更,所以需要將自己注冊到 Eureka 中并保持心跳
- 在 Eureka 之上有一層 Meta Server 用于封裝 Eureka 的服務發(fā)現(xiàn)接口
- Client 通過域名訪問 Meta Server 獲取 Config Service 服務列表(IP+Port)紫岩,而后直接通過 IP+Port 訪問服務,同時在 Client 側會做 load balance烂叔、錯誤重試
- Portal 通過域名訪問 Meta Server 獲取 Admin Service 服務列表 IP+Port德撬,而后直接通過 IP+Port 訪問服務铲咨,同時在 Portal 側會做 load balance、錯誤重試
部署策略
上圖描述了 Apollo 的部署策略:
- PortalDB 主要保存權限蜓洪、支持的環(huán)境等數(shù)據(jù)纤勒,Apollo Portal 環(huán)境只需要部署一套,管理所有環(huán)境(DEV隆檀、FAT摇天、UAT粹湃、PRO)
- ConfigDB 保存應用相關的配置數(shù)據(jù),每個環(huán)境需要獨立的 ConfigDB 數(shù)據(jù)庫
- 為保證穩(wěn)定性泉坐,PortalDB 和 ConfigDB 需要支持 Master-Slave 模式
- 為簡化部署为鳄,實際上會把 Config Service、Eureka 和 Meta Server 部署在同一個 JVM 進程中腕让,Admin Service 部署在另一個 JVM 線程中
- Meta Server孤钦、Eureka 、Config Service 和 Admin Service 在生產環(huán)境可部署在兩個機房纯丸,實現(xiàn)雙活
客戶端架構
上圖簡要描述了 Apollo 客戶端的實現(xiàn)原理:
- 客戶端和服務端保持了一個長連接偏形,從而能第一時間獲得配置更新的推送
- 客戶端會定時從 Apollo 配置中心服務端拉取應用的最新配置(防止推送機制失效導致配置不更新)
- 客戶端從 Apollo 配置中心服務端獲取到應用的最新配置后,會保存在內存中
- 客戶端會把從服務端獲取到的配置在本地文件系統(tǒng)緩存一份液南,在遇到服務不可用壳猜,或網(wǎng)絡不通的時候,依然能從本地恢復配置
- 應用程序從 Apollo 客戶端獲取最新的配置滑凉、訂閱配置更新通知
分布式部署
通過以上的介紹统扳,可以看出 Apollo 的整體架構并不簡單,但其實也不用擔心畅姊,在部署上也并沒那么復雜咒钟。接下來主要介紹 Apollo 的分布式部署,之后的文章中會介紹如何在 Java若未、.NET 客戶端中使用朱嘴,部署將使用 Docker 的方式,所以讀者最好有一定的 Docker 基礎粗合。
有 Apollo 用戶已經提供了現(xiàn)成的 Dcoker 鏡像,我們可以直接使用隙疚。不過這里還是將通過編譯源代碼的方式來介紹壤追,目的是從最原始操作開始,了解整個過程的實現(xiàn)供屉。
環(huán)境要求
- JDK 1.8+ (安裝后行冰,修改 Path 環(huán)境變量)
- Maven 3.5+ (安裝后,修改 Path 環(huán)境變量伶丐,建議修改 Maven 源地址悼做,加快下載速度)
- MySQL 5.6.5+
- Docker
JDK 和 Maven 只在編譯 Apollo 源代碼時使用,實際使用 Docker 部署并不需要哗魂。
創(chuàng)建數(shù)據(jù)庫
從部署策略圖中可以看出肛走,搭建 Apollo 環(huán)境需要使用到 PortalDB、ConfigDB 兩個數(shù)據(jù)庫录别,這兩個數(shù)據(jù)庫的初始腳本官方源碼中已提供:
我們需要在自己的數(shù)據(jù)庫上執(zhí)行以上兩個文件的腳本朽色,這里將搭建一個基于 PRO 的分布式環(huán)境( 如果需要支持多個環(huán)境故硅,需要在對應環(huán)境的數(shù)據(jù)庫上建 ConfigDB,服務啟動改成對應環(huán)境的數(shù)據(jù)庫連接纵搁,更多請參考 調整ApolloPortalDB配置 和 調整ApolloConfigDB配置 )吃衅,如下:
構建 Docker 鏡像
下載最新 apollo master 分支 代碼(當前是 1.5.0-SNAPSHOT),網(wǎng)上很多介紹都需要修改源代碼后再進行編譯腾誉,這個版本已有哥們提交了 Merge Request 徘层,使在 Docker 部署上更簡化了。如有特殊需要利职,也可自行修改源碼
下載完成后在根目錄下執(zhí)行
.\scripts\build.bat
(我是在 windows 進行編譯的)趣效,編譯成功后在apollo-adminservice
、apollo-configservice
猪贪、apollo-portal
下的 target 目錄會生成對應壓縮包pollo-configservice-1.5.0-SNAPSHOT-github.zip
跷敬、apollo-adminservice-1.5.0-SNAPSHOT-github.zip
、apollo-portal-1.5.0-SNAPSHOT-github.zip
热押,這個幾個文件就是我們在構建 Docker 鏡像需要的-
Apollo源碼中已經提供了構建 Docker 鏡像的 Dockerfile 文件西傀,
apollo-configservice\src\main\docker\Dockfile
、apollo-adminservice\src\main\docker\Dockfile
桶癣、apollo-portal\src\main\docker\Dockfile
可以直接使用拥褂,最終如下: 分別構建 Docker 鏡像,然后可以通過 docker push 推送到自己的 Docker 倉庫牙寞,比如 我的倉庫 饺鹃,或者在要部署是機器上生成 Docker 鏡像直接使用,最終得到
apollo-configservice
间雀、apollo-adminservice
悔详、apollo-portal
3個鏡像。
編寫 docker-compose
apollo-configservice && apollo-adminservice:
version: '3'
services:
apollo-configservice:
image: apollo-configservice:latest # 鏡像地址惹挟,這里使用的是直接在當前主機上構建的鏡像
ports:
- "8080:8080"
volumes:
# 日志掛載
- /usr/local/apollo/servers/server2/logs/apollo-configservice:/opt/logs
environment:
# 可通過 SERVER_PORT 指定默認啟動端口茄螃,ports 也需要對應修改
# SERVER_PORT: 8080
# 指定 homePageUrl 為當前宿主的 apollo-configservice 地址,不然會出現(xiàn)無法訪問
JAVA_OPTS: "-Deureka.instance.homePageUrl=http://${當前主機IP}:8080"
# 數(shù)據(jù)庫連接地址
DS_URL: "jdbc:mysql://${數(shù)據(jù)庫IP}:${數(shù)據(jù)庫Port}/ApolloConfigDB?characterEncoding=utf8"
# 數(shù)據(jù)庫用戶名
DS_USERNAME: "apollo"
# 數(shù)據(jù)庫密碼
DS_PASSWORD: "123456"
apollo-adminservice:
image: apollo-adminservice:latest # 鏡像地址匪煌,這里使用的是直接在當前主機上構建的鏡像
ports:
- "8090:8090"
volumes:
# 日志掛載
- /usr/local/apollo/servers/server2/logs/apollo-adminservice:/opt/logs
environment:
# 指定 homePageUrl 為當前宿主的 apollo-adminservice 地址责蝠,不然會出現(xiàn)無法訪問
JAVA_OPTS: "-Deureka.instance.homePageUrl=http://${當前主機IP}:8090"
# 數(shù)據(jù)庫連接地址
DS_URL: "jdbc:mysql://${數(shù)據(jù)庫IP}:${數(shù)據(jù)庫Port}/ApolloConfigDB?characterEncoding=utf8"
# 數(shù)據(jù)庫用戶名
DS_USERNAME: "apollo"
# 數(shù)據(jù)庫密碼
DS_PASSWORD: "123456"
depends_on:
- apollo-configservice
apollo-portal:
version: '3'
services:
apollo-portal:
image: apollo-portal:latest # 鏡像地址党巾,這里使用的是直接在當前主機上構建的鏡像
container_name: apollo-portal
ports:
- "8070:8070"
volumes:
# 日志掛載
- /usr/local/apollo/servers/server1/logs/apollo-portal:/opt/logs
environment:
# 數(shù)據(jù)庫連接地址
DS_URL: "jdbc:mysql://${數(shù)據(jù)庫IP}:${數(shù)據(jù)庫Port}/ApolloPortalDB?characterEncoding=utf8"
# 數(shù)據(jù)庫用戶名
DS_USERNAME: "apollo"
# 數(shù)據(jù)庫密碼
DS_PASSWORD: "123456"
# META_SERVER 地址萎庭,如 http://192.168.100.234:8080,http://192.168.100.234:8081(多個可用,分隔,建議使用 LB 域名),
PRO_META: "http://${實例1的 apollo-configservice 地址},http://${實例2的 apollo-configservice 地址}"
初始數(shù)據(jù)庫數(shù)據(jù)修改
ApolloPortalDB 庫的 ServerConfig 表 apollo.portal.envs
和 configView.memberOnly.envs
值修改為:pro
齿拂;(因為這里我們搭建的是 PRO 的分布式環(huán)境)
ApolloConfigDB 庫的 ServerConfig 表 eureka.service.url
值修改為:http://${實例1的 apollo-configservice 地址}/eureka/,http://${實例2的 apollo-configservice 地址}/eureka/
驳规;
啟動服務
這里將在同一個機器上啟動 1 個 apollo-portal 實例(端口 8070),2 個 apollo-configservice(端口 8080署海、8081)和 2 個 apollo-adminservice(端口 8090吗购、8091)医男。
注意:啟動的過程會比較慢,一般會在 100~200s 左右
通過訪問 http://${apollo-portal 服務IP}:8070
捻勉,輸入默認用戶名密碼 apollo/admin 登錄:(當前的測試腳本提供一個默認的測試項目镀梭,新版本的 sql 腳本可能沒有 SampleApp)
通過 管理員工具 => 系統(tǒng)信息 可查看當前環(huán)境信息:
可以看出 Config Services 和 Admin Services 都是兩個實例,我們可以模擬 kill 其中一臺踱启,服務依然是可以正常使用的报账。
接下來就可以創(chuàng)建應用,添加配置信息埠偿,提供給客戶端使用透罢,具體客戶端如何使用后續(xù)將會繼續(xù)介紹。