Spring Boot 2.0 整合攜程Apollo配置中心

原文:https://www.jianshu.com/p/23d695af7e80javascript

 

Apollo(阿波羅)是攜程框架部門研發的分佈式配置中心,可以集中化管理應用不一樣環境、不一樣集羣的配置,配置修改後可以實時推送到應用端,而且具有規範的權限、流程治理等特性,適用於微服務配置管理場景。css

服務端基於Spring Boot和Spring Cloud開發,打包後能夠直接運行,不須要額外安裝Tomcat等應用容器。java

Java客戶端不依賴任何框架,可以運行於全部Java運行時環境,同時對Spring/Spring Boot環境也有較好的支持。mysql

.Net客戶端不依賴任何框架,可以運行於全部.Net運行時環境。git

若是想要深刻了解,能夠到github上參見Apollo配置中心,官網的介紹很詳細。本章主要講述Spring Boot 2.0 整合Apollo配置中心。github

1、Apollo配置中心服務端(來源於官網)

本文的重點在於Apollo在客戶端的使用,因此Apollo服務端使用的是官網提供的 Quick Start(針對本地測試使用),後續文章會專門講述Apollo服務端在分佈式環境下的部署。redis

1.1 準備工做

  1. Java
    Apollo服務端要求Java 1.8+,客戶端要求Java 1.7+,筆者本地使用的是Java 1.8。
  2. MySQL
    Apollo的表結構對timestamp使用了多個default聲明,因此須要5.6.5以上版本。筆者本地使用的是8.0.13版本
  3. 下載 Quick Start
    官網爲咱們準備了 Quick Start 安裝包。你們只須要下載到本地,就能夠直接使用,免去了編譯、打包過程。你們能夠到github下載,也能夠經過百度雲盤下載

1.2 安裝步驟

1.2.1 建立數據庫

Apollo服務端共須要兩個數據庫:ApolloPortalDB和ApolloConfigDB,官網把數據庫、表的建立和樣例數據都分別準備了sql文件(在下載的 Quick Start 安裝包的sql目錄下),只須要導入數據庫便可。sql

1.2.1.1 建立ApolloPortalDB

經過各類Mysql客戶端(Navicat,DataGrip等)導入sql/apolloportaldb.sql便可
下面以MySQL原生客戶端爲例:數據庫

source /your_local_path/sql/apolloportaldb.sql 

導入成功後,能夠經過執行如下sql語句來驗證:json

select `Id`, `AppId`, `Name` from ApolloPortalDB.App; 
Id AppId Name
1 SampleApp Sample App
1.2.1.2 建立ApolloConfigDB

經過各類Mysql客戶端(Navicat,DataGrip等)導入sql/apolloconfigdb.sql便可
下面以MySQL原生客戶端爲例:

source /your_local_path/sql/apolloconfigdb.sql 

導入成功後,能夠經過執行如下sql語句來驗證:

select `NamespaceId`, `Key`, `Value`, `Comment` from ApolloConfigDB.Item; 
NamespaceId Key Value Comment
1 timeout 100 sample timeout配置

1.2.2 配置數據庫鏈接信息

Apollo服務端須要知道如何鏈接到你前面建立的數據庫,因此須要編輯demo.sh,修改ApolloPortalDB和ApolloConfigDB相關的數據庫鏈接串信息。

#apollo config db info apollo_config_db_url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8 apollo_config_db_username=用戶名 apollo_config_db_password=密碼(若是沒有密碼,留空便可) # apollo portal db info apollo_portal_db_url=jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8 apollo_portal_db_username=用戶名 apollo_portal_db_password=密碼(若是沒有密碼,留空便可) 

1.3 啓動Apollo配置中心

1.3.1 確保端口未被佔用

Quick Start腳本會在本地啓動3個服務,分別使用8070, 8080, 8090端口,請確保這3個端口當前沒有被使用。例如,在Linux/Mac下,能夠經過以下命令檢查:

lsof -i:8080 

在windows下,能夠經過以下命令檢查:

netstat -aon|findstr "8080" 

1.3.2 執行啓動腳本

在Quick Start目錄下執行以下命令:

./demo.sh start

當看到以下輸出後,就說明啓動成功了!

==== starting service ====
Service logging file is ./service/apollo-service.log Started [10768] Waiting for config service startup....... Config service started. You may visit http://localhost:8080 for service status now! Waiting for admin service startup.... Admin service started ==== starting portal ==== Portal logging file is ./portal/apollo-portal.log Started [10846] Waiting for portal startup...... Portal started. You can visit http://localhost:8070 now! 

1.3.3 異常排查

若是啓動遇到了異常,能夠分別查看service和portal目錄下的log文件排查問題。

注: 在啓動apollo-configservice的過程當中會在日誌中輸出eureka註冊失敗的信息,如com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused。須要注意的是,這個是預期的狀況,由於apollo-configservice須要向Meta Server(它本身)註冊服務,可是由於在啓動過程當中,本身還沒起來,因此會報這個錯。後面會進行重試的動做,因此等本身服務起來後就會註冊正常了。

1.4 使用Apollo配置中心

1.4.1 查看樣例配置

  1. 瀏覽器訪問http://localhost:8070
    登陸界面
    登陸界面

    Quick Start集成了Spring Security簡單認證,更多信息能夠參考Portal 實現用戶登陸功能
  2. 輸入用戶名apollo,密碼admin登陸
    項目界面
    項目界面

    配置中心中包含一個默認的項目SampleApp
  3. 點擊SampleApp進入配置界面,能夠看到當前有一個配置timeout=100


    項目配置詳情
    項目配置詳情

    若是提示系統出錯,請重試或聯繫系統負責人,請稍後幾秒鐘重試一下,由於經過Eureka註冊的服務有一個刷新的延時。

1.4.2 新增項目配置

咱們的客戶端使用apollo須要新增相關的項目配置。

  1. 點擊新建項目


    項目信息
    項目信息
    • 應用ID:這個ID是應用的惟一標識
    • 應用名稱:應用的名稱,會展現在配置中心的首頁上

    點擊提交,建立完成


    應用配置界面
    應用配置界面
  2. 新增配置信息

     

    點擊新增配置,填寫配置信息
    配置信息
    配置信息
    點擊提交,此時配置還未生效。
    未發佈的配置
    未發佈的配置
  3. 發佈配置
    點擊發布,配置馬上生效


    生效的配置
    生效的配置
  4. 回滾
    若是配置作了修改以後,發現配置更改錯誤,這個時候可使用回滾功能,回到上一個配置


    回滾配置
    回滾配置

2、Apollo配置中心客戶端

咱們客戶端基於Spring Boot 2.0搭建,開發工具是InteIIij IDEA。新建一個項目,項目名稱爲apollo-client

2.1 客戶端搭建

  1. 添加Apollo客戶端依賴
    <dependency> <groupId>com.ctrip.framework.apollo</groupId> <artifactId>apollo-client</artifactId> <version>1.1.1</version> </dependency> 
    目前最新版本爲1.1.1
  2. 添加配置信息
    # 應用ID(在Apollo服務端新增項目添加的應用ID) app.id=testclient # apollo-configservice地址 apollo.meta=http://127.0.0.1:8080 
  3. 開啓Apollo客戶端
    在項目的啓動類上添加@EnableApolloConfig註解
  4. 新增一個測試接口
@RequestMapping("/index") public String hello(){ return "hello man"; } 
  1. 啓動服務測試
    在Apollo配置中心中,咱們對該項目有一條配置server.port = 9000,啓動服務,訪問http://localhost:9000/index,返回hello man。證實,客戶端是從服務端獲取的配置。

2.2 客戶端用法

在上一節,咱們簡單的搭建了客戶端,成功的使用服務端配置。Apollo爲咱們提供的使用方式有不少種,下面只介紹Spring Boot 2.0環境下的使用方式。

2.2.1 Spring Placeholder的使用

Spring應用一般會使用Placeholder來注入配置,使用的格式形如${someKey:someDefaultValue},如${timeout:100}。冒號前面的是key,冒號後面的是默認值(建議在實際使用時儘可能給出默認值,以避免因爲key沒有定義致使運行時錯誤)。Apollo從v0.10.0開始的版本支持placeholder在運行時自動更新。若是須要關閉placeholder在運行時自動更新功能,能夠經過如下兩種方式關閉:

  1. 經過設置System Property apollo.autoUpdateInjectedSpringProperties,如啓動時傳入-Dapollo.autoUpdateInjectedSpringProperties=false
  2. 經過設置META-INF/app.properties中的apollo.autoUpdateInjectedSpringProperties=false
2.2.1.1 Java Config使用方式
  1. 新建配置類JavaConfigBean以下:
    /** * Java Config方式 * * @author simon * @create 2018-11-02 15:00 **/ @Configuration public class JavaConfigBean { @Value("${timeout:20}") private int timeout; public int getTimeout() { return timeout; } } 
  2. 新增訪問端點
    //1.Java Config方式 @Autowired JavaConfigBean javaConfigBean; @RequestMapping("/index1") public String hello1(){ return javaConfigBean.getTimeout()+""; } 
  3. 測試
    瀏覽器訪問http://127.0.0.1:8080/index1,正確返回配置的值
2.2.1.2 ConfigurationProperties使用方式

Spring Boot提供了@ConfigurationProperties把配置注入到bean對象中。Apollo也支持這種方式,下面的例子會把redis.cache.expireSecondsredis.cache.commandTimeout分別注入到SampleRedisConfigexpireSecondscommandTimeout字段中。

  1. 新增配置類SampleRedisConfig以下:
    /** * ConfigurationProperties使用方式 * * @author simon * @create 2018-11-02 9:30 **/ @Configuration @ConfigurationProperties(prefix = "redis.cache") public class SampleRedisConfig { private int expireSeconds; private int commandTimeout; public void setExpireSeconds(int expireSeconds) { this.expireSeconds = expireSeconds; } public void setCommandTimeout(int commandTimeout) { this.commandTimeout = commandTimeout; } public int getExpireSeconds() { return expireSeconds; } public int getCommandTimeout() { return commandTimeout; } } 
  2. 新增訪問端點
    //2. ConfigurationProperties使用方式 @Autowired SampleRedisConfig sampleRedisConfig; @RequestMapping("/index2") public String hello2(){ return sampleRedisConfig.getCommandTimeout()+"--"+sampleRedisConfig.getExpireSeconds(); } 
  3. 測試
    瀏覽器訪問http://127.0.0.1:8080/index2,正確返回配置的值

注: @ConfigurationProperties若是須要在Apollo配置變化時自動更新注入的值,須要配合使用EnvironmentChangeEventRefreshScope。這個我會在後續文章中詳細描述。

2.2.2 Spring Annotation支持

Apollo同時還增長了幾個新的Annotation來簡化在Spring環境中的使用。

  • @ApolloConfig用來自動注入Config對象
  • @ApolloConfigChangeListener用來自動註冊ConfigChangeListener
  • @ApolloJsonValue用來把配置的json字符串自動注入爲對象
2.2.2.1 @ApolloConfig的使用
  1. 新增訪問端點
    // 3. @ApolloConfig使用 @ApolloConfig private Config config; @RequestMapping("/index3") public String hello3(){ Set <String> propertyNames = config.getPropertyNames(); propertyNames.forEach(key -> { System.err.println(key+"="+config.getIntProperty(key,0)); }); return propertyNames.toString(); } 
  2. 測試
    瀏覽器訪問http://127.0.0.1:8080/index3,正確打印配置的值
    redis.cache.commandTimeout=3000
    redis.cache.expireSeconds=20
    server.port=800
    timeout=200
2.2.2.2 @ApolloConfigChangeListener的使用
  1. 新增如下代碼
    @ApolloConfigChangeListener private void someOnChange(ConfigChangeEvent changeEvent) { //update injected value of batch if it is changed in Apollo if (changeEvent.isChanged("timeout")) { System.out.println(config.getIntProperty("timeout", 0)); } } 
  2. 測試
    在Apollo服務端修改timeout配置的值爲300,發佈後,控制檯打印300
2.2.2.3 @ApolloJsonValue的使用
  1. 新增User以下:
    /** * 用戶 * * @author simon * @create 2018-11-02 16:41 **/ public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } 
  2. 服務端新增配置
    jsonBeanProperty=[ { "username": "john", "password": "1234" }, { "username": "simon", "password": "222132" } ]
  3. 客戶端獲取配置
    //4. @ApolloJsonValue使用 @ApolloJsonValue("${jsonBeanProperty:[]}") private List<User> anotherJsonBeans; @RequestMapping("/index4") public void hello4(){ anotherJsonBeans.forEach(item -> { System.err.println(item.getUsername()+"--"+item.getPassword()); }); } 
  4. 測試
    瀏覽器訪問http://127.0.0.1:8080/index4,正確打印配置的值

源碼下載 

相關文章
相關標籤/搜索