Apollo功能及原理詳解

LemonDus發表於2024-12-08

前言

公司裡面使用的配置中心是攜程開源的Apollo,之前我只使用過Nacos,遂記錄一下學習過程。

Apollo工作原理

apollo_yl

模組介紹

上圖就是Apollo的總體設計,從下往上挨個分析:

  • ConfigDB用於儲存各種配置
  • Config Service提供配置的讀取、推送等功能,服務物件是Apollo客戶端,多例項,需要註冊到Eureka中保持心跳檢測
  • Admin Service提供配置的修改、釋出等功能,服務物件是Apollo Portal(管理介面),多例項,需要註冊到Eureka中保持心跳檢測
  • Eureka提供服務註冊和發現,為了簡單起見,目前Eureka在部署時和Config Service是在一個JVM程序中
  • Meta Server用於封裝Eureka的服務發現介面
  • Client透過域名訪問Meta Server獲取Confifig Service服務列表(IP+Port),而後直接透過IP+Port訪問服務,同時在Client側會做load balance、錯誤重試
  • Portal透過域名訪問Meta Server獲取Admin Service服務列表(IP+Port),而後直接透過IP+Port訪問服務,同時在Portal側會做load balance、錯誤重試

執行流程

  1. Apollo啟動後,Config/Admin Service會自動註冊到Eureka服務註冊中心,並定期傳送保活心跳;
  2. Apollo Client和Portal管理端透過配置的Meta Server的域名地址經由Software Load Balancer(軟體負載均衡器)進行負載均衡後分配到某一個Meta Server;
  3. Meta Server從Eureka獲取Config Service和Admin Service的服務資訊,相當於是一個Eureka Client;
  4. Meta Server獲取Config Service和Admin Service(IP+Port)失敗後會進行重試;
  5. 獲取到正確的Config Service和Admin Service的服務資訊後,Apollo Client透過Config Service為應用提供配置獲取、實時更新等功能;Apollo Portal管理端透過Admin Service提供配置新增、修改、釋出等功能。

基本概念

  • application (應用)
    實際使用配置的應用,Apollo客戶端在執行時需要知道當前應用是誰,從而可以去獲取對應的配置。關鍵字:appId
  • environment (環境)
    配置對應的環境,Apollo客戶端在執行時需要知道當前應用處於哪個環境,從而可以去獲取應用的配置。關鍵字:env
  • cluster (叢集)
    一個應用下不同例項的分組,比如典型的可以按照資料中心分,把上海機房的應用例項分為一個叢集,把北京機房的應用例項分為另一個叢集。關鍵字:cluster
  • namespace (名稱空間)
    一個應用下不同配置的分組,可以簡單地把namespace類比為檔案,不同型別的配置存放在不同的檔案中,如資料庫配置檔案,RPC配置檔案,應用自身的配置檔案等。關鍵字:namespaces
    關係圖如下所示:
    apollo_gxt

專案管理

部門管理

apollo 預設部門有兩個。要增加自己的部門,可在系統引數中修改,進入系統引數,輸入key查詢已存在的部門設定:organizations
apollo_bumen
修改value值來新增新部門,下面新增一個微服務部門:

[{"orgId":"TEST1","orgName":"樣例部門1"},{"orgId":"TEST2","orgName":"樣例部門2"},{"orgId":"micro_service","orgName":"微服務部門"}]

建立專案

  1. 開啟apollo主頁,點選建立應用:
    apollo_chuangjian
  2. 輸入相關資訊,包括部門、應用AppId、應用名稱和應用負責人
    apollo_yingyongxinxi
  3. 將專案授予使用者管理服務的許可權,點選授權
    apollo_shouquan
  4. 使用zhangsan賬號登陸,就可以看到能管理的應用了
    apollo_chakan

刪除專案

如果要刪除整個專案,點選右上角的管理員工具,再點選刪除應用、叢集。

首先查出壓迫刪除的專案是,然後點選刪除應用:
apollo_chakan

配置管理

釋出配置

  • 透過表格模式新增:
    apollo_bgtj
  • 透過文字模式批次新增:
    apollo_wbtj
  • 最後點選右上角釋出按鈕釋出配置。

修改配置

找到需要修改的配置項,進行修改
apollo_update
修改完進行提交,之後在重新發布配置。

刪除配置

與上面一樣,刪除配置後重新發布。

設定私有Namespace

Namespace同樣也可以當作一個配置檔案,以rocketmq配置為例,新增“spring-rocketmq” Namespace配置rocketmq相關資訊。

  1. 建立名稱空間
    apollo_mmkj
  2. 新增配置項
    apollo_namesettings
  3. 進行釋出。

設定公共Namespace

在專案開發中,有一些配置可能是通用的,我們可以透過把這些通用的配置放到公共的Namespace中,這樣其他專案要使用時可以直接新增需要的Namespace。

新增配置

  1. 新建一個common-template專案
    apollo_publicname
  2. 新增公共Namespace:spring-boot-http
    apollo_publicnamecreate
  3. 新增配置項併發布
    apollo_publicsettings

關聯公共Namespcae

建立完公共名稱空間之後,需要將專案進行關聯才能使用。

開啟之前建立的account-service專案,點選左側的新增Namespace,再新增Namespace:
apollo_guanlian

若是當前專案需要的配置與公共配置中提供的不一樣,也可以根據需求覆蓋定製配置。

讀取配置

讀取某個叢集的配置,需要啟動應用時在VM option指定具體的應用、環境和叢集。

-Dapp.id=應用名稱

-Denv=環境名稱

-Dapollo.cluster=叢集名稱

-D環境_meta=meta地址

具體例項如下:

‐Dapp.id=account‐service 
‐Denv=DEV 
‐Dapollo.cluster=SHAJQ 
‐Dapollo.meta=http://localhost:8080

配置釋出原理分析

在配置中心中,一個重要的功能就是配置釋出後實時推送到客戶端。下面我們簡要看一下這塊是怎麼設計實現的:
apollo_shishiyuanli

  1. 使用者在Portal操作配置釋出
  2. Portal呼叫Admin Service的介面操作釋出
  3. Admin Service釋出配置後,傳送ReleaseMessage給各個Config Service
  4. Config Service收到ReleaseMessage後,通知對應的客戶端

原始碼分析

傳送ReleaseMessage

Admin Service在配置釋出後,需要通知所有的Config Service有配置釋出,從而Config Service可以通知對應的客戶端來拉取最新的配置。

從概念上來看,這是一個典型的訊息使用場景,Admin Service作為producer(生產者)發出訊息,各個Config Service作為consumer(消費者)消費訊息。透過一個訊息佇列元件(Message Queue)就能很好的實現Admin Service和Config Service的解耦。

在實現上,考慮到Apollo的實際使用場景,以及為了儘可能減少外部依賴,Apollo沒有采用外部的訊息中介軟體,而是透過資料庫實現了一個簡單的訊息佇列。

具體實現如下:

  1. Admin Service在配置釋出後會往ReleaseMessage表插入一條訊息記錄,訊息內容就是配置釋出的AppId+Cluster+Namespace:

    訊息傳送類:DatabaseMessageSende
    apollo_ym_fb

  2. Config Service有一個執行緒會每秒掃描一次ReleaseMessage表,看看是否有新的訊息記錄。

    訊息掃描類:ReleaseMessageScanner
    apollo_ym_sm

  3. Config Service如果發現有新的訊息記錄,那麼就會通知到所有的訊息監聽器
    apollo_ym_tz

  4. 有一個類叫NotifificationControllerV2,當它得到配置釋出的AppId+Cluster+Namespace後,會通知對應的客戶端。

    1. 客戶端會發起一個Http請求到Config Service的 notifications/v2 介面NotificationControllerV2
      apollo_ym_NotificationControllerV2
    2. NotificationControllerV2不會立即返回結果,而是把請求掛起。考慮到會有數萬客戶端向服務端發起長連,因此在服務端使用了async servlet(Spring DeferredResult)來服務Http Long Polling請求。
    3. 如果在60秒內沒有該客戶端關心的配置釋出,那麼會返回Http狀態碼304給客戶端。
    4. 如果有該客戶端關心的配置釋出,NotificationControllerV2會呼叫DeferredResult的setResult方法,傳入有配置變化的namespace資訊,同時該請求會立即返回。客戶端從返回的結果中獲取到配置變化的namespace 後,會立即請求Config Service獲取該namespace的最新配置。
    5. 除此之外,客戶端還會定時從Apollo配置中心服務端拉取應用的最新配置,防止推送機制失效導致配置不更新,提升了可用性,預設定時拉取頻率是5分鐘。

相關文章