攜程apollo系列-客戶端集成


本文講解如何在 Java 程序中集成 Apollo 配置, 主要涉及到一些基礎用法.
對於一些高級用法, 比如如何加密/解密配置項 (可用於數據庫密碼配置), 如何動態切換數據源地址,如何動態切換日志級別,

可以參考官方的 user cases git 庫, 官方代碼庫 https://github.com/ctripcorp/apollo-use-cases 和 InfoQ 微信文章: GitHub 9K Star!Apollo作者手把手教你微服務配置中心之道 

在開始集成之前, 先了解一些 apollo 相關概念.

================================================
基本概念
================================================
Apollo 幾個術語的從屬關系: 環境>項目>集群>命名空間.

1. 集群概念
這里的集群不是指 apollo 配置中心集群, 而是指受管項目的集群. 另外需要區分集群和環境術語的差異, 這里的集群相當於數據中心 (idc) 的概念, 比如一個大型系統的生產環境, 可能會部署在多個不同的數據中心.
一個應用可以包含多個集群, 缺省的集群名為"default", 比如在不同機房, 項目使用到 redis 地址不同. 如果不同 idc 使用同樣的配置, 則沒有必要創建集群. 對於一般項目而言都是部署在同一個數據中心中, 沒有必要專門新加集群.
如果在 apollo 中為某個應用配置了集群, 需要在應用的文件系統中, 告知所在集群的名字, 方法是:
在 /opt/settings/server.properties(linux) 文件 或 C:\opt\settings\server.properties(windows) 文件中, 設定 idc 屬性值為集群名稱.


2. Namespace 概念:
namespace 可以認為是配置項的一個容器, 類似於配置文件的概念.
namespace 的作用:
(1). 作為配置項的一個容器
(2). 用於細化權限管控, 比如某個命名空間只允許 DBA 修改和發布, 另一個只允許運維修改和發布.
(3). 用於配置項版本整體回滾
一個應用可以包含多個 namespace, 缺省的 namespace 名為 "application".
添加 namespace 需要指定配置文件格式, 支持 properties/xml/json/yaml 等格式, 缺省的格式為 properties.
正常情況下一個 namespace 應該是從屬於某個應用, 但也可以構建多個應用公用的的 namespace.

對於一個應用而言, namespace 建議分為業務配置和系統配置兩類.
(1)業務配置 namespace: 和業務相關的配置.
(2)系統配置 namespace: 包含數據庫地址/賬號等信息.


3. 環境
apollo 的環境術語和我們平時所講的環境含義一致, 比如開發/生產環境. apollo 后台的 apolloconfigdb 表僅支持一個環境, 如果要支持多個環境, 必須有多個 MySQL 服務器和多個 config service, 但 apollo portal 是支持多環境集中管理.
apollo 支持 DEV/UAT/PRO/FAT 等環境名稱, 大小寫不敏感, 還有一個特別的 Local 環境名, 代表程序時僅讀取本地緩存目錄下的配置文件.

支持的環境名有:
DEV -- dev 環境
FAT -- feature Acceptance test
UAT -- user Acceptance test
PRO -- production 環境
Local -- 讀取本地緩存目錄下的配置文件

設置 env=Local, 程序僅讀本地緩存目錄下的配置文件, 下面是缺省的本地緩存路徑, 可以通過 apollo.cacheDir 參數來調整缺省的緩存路徑
## Mac/Linux: /opt/data/{appId}/config-cache
## Windows: C:\opt\data\{appId}\config-cache
具體的緩存文件名為: {appId}+{cluster}+{namespace}.properties


================================================
pom.xml
================================================

增加 apollo-client 依賴.

<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-client</artifactId>
    <version>1.1.0</version>
</dependency>

 

================================================
設定遠程 Apollo 服務器連接信息
================================================
Apollo 提供很多方式來設定遠程配置服務, 下面僅僅列出其中一些方式.
接入Apollo的 SpringBoot 程序, 推薦使用 System property 配置 apollo 參數,  application.properties不要再配加任何參數, 僅僅保留一個空文件, 其他參數都配在 apollo 中, 當然我們不能把apollo服務器連接參數配到apollo中. 

另外, 一旦接入了 apollo 系統, 如果 application.properties 和 apollo 中有同名的參數, 以apollo中的配置為准. 

方式 1: 通過 System property 形式, 比如命令行增加參數:
System property 支持所有的參數, 黑體字為最重要的參數, 推薦在啟動命令行中設定. 
-Dapp.id=YOUR-APP-ID
-Dapollo.meta=http://config-service-url
-Denv=DEV
-Dapollo.cacheDir=/opt/data/some-cache-dir
-Dapollo.cluster=SomeCluster

對於 meta server, 也可以 -D{env}.meta 這樣的形式指定.


方式 2: 通過 SpringBoot 的 application.properties 文件指定
application.properties 中除了不能指定 env 參數外, 其他都參數都支持.
app.id=YOUR-APP-ID
apollo.meta=http://localhost:8080
apollo.cacheDir=/opt/data/some-cache-dir
apollo.cluster=SomeCluster
apollo.bootstrap.enabled = true
apollo.bootstrap.namespaces = application,other_namespace
apollo.autoUpdateInjectedSpringProperties=true # 自動更新 @Value 注解的屬性


方式 3: 通過 META-INF/app.properties 文件設定
只能用來設置 app.id 和 apollo.meta 參數.
app.properties 文件的位置是: classpath:/META-INF/app.properties
app.id=YOUR-APP-ID
apollo.meta=http://localhost:8080


方式 4: 通過 server.properties 配置文件
不能用來設定 app.id 參數, 主要用來設定這台服務器上的通用設置, 比如 meta 和 cluster 和 cacheDir 等參數, 其中 idc 參數等同於 apollo.cluster 參數.
對於 Mac/Linux, 文件位置為/opt/settings/server.properties
對於 Windows, 文件位置為 C:\opt\settings\server.properties
env=DEV
idc=SomeCluster
apollo.meta=http://config-service-url
apollo.cacheDir=/opt/data/some-cache-dir
dev.meta=http://localhost:8080
fat.meta=http://apollo.fat.xxx.com
uat.meta=http://apollo.uat.xxx.com
pro.meta=http://apollo.xxx.com


方式 5: 通過 apollo-env.properties 設置各環境的服務器地址
主要用來指定 meta server 的地址. apollo-env.properties 文件位置是 resources 目錄下
dev.meta=http://localhost:8080
fat.meta=http://apollo.fat.xxx.com
uat.meta=http://apollo.uat.xxx.com
pro.meta=http://apollo.xxx.com


================================================
Spring 項目和 apollo 集成方式
================================================
Java項目要集成Apollo 有很多種方式, 下面是常用方式:
方式 1: 使用 Java API 方式, 不僅適合 Spring 項目, 而且適合非 Spring 項目, 靈活方便, 支持熱部署.
方式 2: Spring 的 @Value 方式關聯 appollo 配置項. 該方式使用簡單, 但可控性較差.
方式 3: 結合 SpringBoot 的 @ConfigurationProperties 注解. 該方法使用稍微復雜, 但可控性好.
方式 4. 使用 Apollo 的 @ApolloConfig 和 @ApolloConfigChangeListener .
方式 5. Spring 項目通過 Environment, 該方式使用較為麻煩, 推薦使用方式 2 或 3.


----------------------------------------
方式 1: 使用 Java API 方式
----------------------------------------

// 從缺省的獲取 application 命名空間 
Config config = ConfigService.getAppConfig(); 
//獲取其他 namespace 的配置
//Config config = ConfigService.getConfig(String namespace, ConfigFileFormat configFileFormat); 
String someKey = "someKeyFromDefaultNamespace";
String someDefaultValue = "someDefaultValueForTheKey";
String value = config.getProperty(someKey, someDefaultValue);

// 增加監聽事件
config.addChangeListener(new ConfigChangeListener() {
    @Override
    public void onChange(ConfigChangeEvent changeEvent) {
        for (String key : changeEvent.changedKeys()) {
            ConfigChange change = changeEvent.getChange(key);
            System.out.println(String.format("Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s", change.getPropertyName(),
                    change.getOldValue(), change.getNewValue(), change.getChangeType()));
        }
    }
});

 


----------------------------------------
SpringBoot 下預先加載配置項
----------------------------------------
SpringBoot 大量采用了自動裝配機制, 比如 DataSource 實例初始化. 當引入 Apollo 配置中心后, 是否也支持這個特性呢? 答案是肯定的, apollo.bootstrap.namespaces 屬性指定的 namespace 將在 SpringContext 容器初始化時候就加載完畢, 這樣在實例化 bean 時就可能使用 Apollo 配置項了. 需要在 application.properties 中設置下面兩個屬性:
apollo.bootstrap.enabled = true
apollo.bootstrap.namespaces = application,other_namespace

 

----------------------------------------
方式 2: Spring 的 @Value 方式關聯 appollo 配置項
----------------------------------------
在代碼層面該方式僅需要兩個步驟:
步驟 1: 在一個被@Configuration 注解的類上加 @EnableApolloConfig,  比如在 Application 入口類上加 @EnableApolloConfig. @EnableApolloConfig 負責將 apollo 的 namespace 注冊到 Configuration 類中.
步驟 2: 在程序中使用 @Value 引入這個配置項

    @Value("${timeout:1000}")
    private String timeout;


需要說明的是:
1. @EnableApolloConfig 注解必須和@Configuration 搭配使用, 如果沒有指定注解參數, 對應的namespace為 apollo 的 "application" namespace, .
2. 默認情況下, @Value 的屬性會自動更新的, 如果不希望自動更新, 可以在 application.properties 設置:
apollo.autoUpdateInjectedSpringProperties=false # 關閉自動更新 @Value 注解的屬性


----------------------------------------
方式 3: 結合 SpringBoot 的 @ConfigurationProperties 注解.
----------------------------------------


----------------------------------------
方式 4. 使用 Apollo 的 @ApolloConfig 和 @ApolloConfigChangeListener
----------------------------------------
這個方法其實和通過 API 方法非常類似, 僅僅是簡化了代碼.
使用 @ApolloConfig 用來注入一個 apollo config 對象, 使用 @ApolloConfigChangeListener 用來注冊一個監聽事件.
@ApolloConfig(namespace) 可以匹配 apollo 的命名空間, 如不寫, 則指 application 命名空間.
@ApolloConfigChangeListener(namespace) 更新時調用的方法, 如不寫, 則指 application 命名空間.

在代碼層面該方式僅需要兩個步驟:
1. 在一個被@Configuration 注解的類上加 @EnableApolloConfig, 比如在 Application 入口類上加 @EnableApolloConfig.
2. 增加一個 bean 類,在其中使用 @ApolloConfig 和 @ApolloConfigChangeListener 注入 config 對象和監聽事件, 同時加上一個 @PostConstruct 方法來初始化 apollo 配置項原始值.

@EnableApolloConfig
@Component
class ApolloConfigBean {

    @ApolloConfig //注入一個 Apollo Config 對象
    private Config appConfig;

    @PostConstruct // 在 ApolloConfigBean 實例化后, 立即獲取 apollo 配置項值
    public void init() {
        timeout = appConfig.getIntProperty("timeout", 100);
    }

    private int timeout = -1;

    public int getTimeout() {
        return timeout;
    }

    @ApolloConfigChangeListener //注冊一個監聽事件
    private void onChange(ConfigChangeEvent changeEvent) {
        if (changeEvent.isChanged("timeout")) {
            timeout = Integer.parseInt(changeEvent.getChange("timeout")
                    .getNewValue());
        }
        System.out.println("onchange ");
    }
}



----------------------------------------
方式 5. Spring 項目通過 Environment
----------------------------------------



================================================
參考
================================================
Apollo 的基本使用方法
http://ghoulich.xninja.org/2018/04/28/basic-usage-method-of-apollo/
Java 客戶端使用指南
https://github.com/ctripcorp/apollo/wiki/Java 客戶端使用指南
微服務之 SpringCloud 架構第六篇(下)——配置中心(Apollo)
https://blog.csdn.net/pilihaotian/article/details/82958386
Apollo 應用之動態調整線上數據源 (DataSource)
http://www.kailing.pub/article/index/arcid/198.html
SpringBoot 整合攜程 Apollo 配置管理中心
https://www.cnblogs.com/hongdada/p/9015748.html
攜程 Apollo(阿波羅)配置中心在 Spring Boot 項目快速集成
https://www.cnblogs.com/EasonJim/p/7649047.html
Apollo-4-客戶端-SDK-設計
http://thinkinjava.cn/2018/06/Apollo-4-%E5%AE%A2%E6%88%B7%E7%AB%AF-SDK-%E8%AE%BE%E8%AE%A1/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM