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

作者:AaronSimon
來源:https://blog.csdn.net/AaronSimon/article/details/83657612

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

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

Java客戶端不依賴任何框架,能夠運行於所有Java運行時環境,同時對Spring/Spring Boot環境也有較好的支持。

.Net客戶端不依賴任何框架,能夠運行於所有.Net運行時環境。

如果想要深入瞭解,可以到github上參見Apollo配置中心,官網的介紹很詳細。本章主要講述Spring Boot 2.0 整合Apollo配置中心。

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

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

1.1 準備工作

  1. Java
  2. Apollo服務端要求Java 1.8+,客戶端要求Java 1.7+,筆者本地使用的是Java 1.8。
  3. MySQL
  4. Apollo的表結構對timestamp使用了多個default聲明,所以需要5.6.5以上版本。筆者本地使用的是8.0.13版本
  5. 下載 Quick Start
  6. 官網為我們準備了 Quick Start 安裝包。大家只需要下載到本地,就可以直接使用,免去了編譯、打包過程。大家可以到github下載,也可以通過百度雲盤下載


1.2 安裝步驟

1.2.1 創建數據庫

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

1.2.1.1 創建ApolloPortalDB

通過各種Mysql客戶端(Navicat,DataGrip等)導入sql/apolloportaldb.sql即可

下面以MySQL原生客戶端為例:

source /your_local_path/sql/apolloportaldb.sql


導入成功後,可以通過執行以下sql語句來驗證:

select `Id`, `AppId`, `Name` from ApolloPortalDB.App;
Spring Boot 2.0 整合攜程Apollo配置中心

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;
Spring Boot 2.0 整合攜程Apollo配置中心

1.2.2 配置數據庫連接信息

Apollo服務端需要知道如何連接到你前面創建的數據庫,所以需要編輯demo.sh,修改ApolloPortalDB和ApolloConfigDB相關的數據庫連接串信息。

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

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


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

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

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
Spring Boot 2.0 整合攜程Apollo配置中心


  1. Quick Start集成了Spring Security簡單認證,更多信息可以參考Portal 實現用戶登錄功能
  2. 輸入用戶名apollo,密碼admin登錄
Spring Boot 2.0 整合攜程Apollo配置中心


  1. 配置中心中包含一個默認的項目SampleApp
  2. 點擊SampleApp進入配置界面,可以看到當前有一個配置timeout=100
Spring Boot 2.0 整合攜程Apollo配置中心


  1. 如果提示系統出錯,請重試或聯繫系統負責人,請稍後幾秒鐘重試一下,因為通過Eureka註冊的服務有一個刷新的延時。

1.4.2 新增項目配置

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

點擊新建項目

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

點擊提交,創建完成

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

  • 應用ID:這個ID是應用的唯一標識
  • 應用名稱:應用的名稱,會展示在配置中心的首頁上

  1. 新增配置信息
  2. 點擊新增配置,填寫配置信息
Spring Boot 2.0 整合攜程Apollo配置中心

  1. 點擊提交,此時配置還未生效。
Spring Boot 2.0 整合攜程Apollo配置中心


  1. 發佈配置
  2. 點擊發布,配置立刻生效
Spring Boot 2.0 整合攜程Apollo配置中心


  1. 回滾
  2. 如果配置做了修改之後,發現配置更改錯誤,這個時候可以使用回滾功能,回到上一個配置
Spring Boot 2.0 整合攜程Apollo配置中心


二、Apollo配置中心客戶端

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

2.1 客戶端搭建

添加Apollo客戶端依賴


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

添加配置信息

# 應用ID(在Apollo服務端新增項目添加的應用ID)
app.id=testclient
# apollo-configservice地址
apollo.meta=http://127.0.0.1:8080開啟Apollo客戶端

  1. 在項目的啟動類上添加@EnableApolloConfig註解

新增一個測試接口

@RequestMapping("/index")
public String hello(){
return "hello man";
}

啟動服務測試

在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如下:
Spring Boot 2.0 整合攜程Apollo配置中心

新增訪問端點

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

  1. 測試
  2. 瀏覽器訪問http://127.0.0.1:8080/index1,正確返回配置的值

2.2.1.2 ConfigurationProperties使用方式

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

  1. 新增配置類SampleRedisConfig如下:

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

  1. 新增訪問端點

//2. ConfigurationProperties使用方式
@Autowired
SampleRedisConfig sampleRedisConfig;
@RequestMapping("/index2")
public String hello2(){
return sampleRedisConfig.getCommandTimeout()+"--"+sampleRedisConfig.getExpireSeconds();
}
  1. 測試
  2. 瀏覽器訪問http://127.0.0.1:8080/index2,正確返回配置的值

注: @ConfigurationProperties如果需要在Apollo配置變化時自動更新注入的值,需要配合使用EnvironmentChangeEvent或RefreshScope。這個我會在後續文章中詳細描述。

2.2.2 Spring Annotation支持

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

  • @ApolloConfig用來自動注入Config對象
  • @ApolloConfigChangeListener用來自動註冊ConfigChangeListener
  • @ApolloJsonValue用來把配置的json字符串自動注入為對象

2.2.2.1 @ApolloConfig的使用

  1. 新增訪問端點

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

  1. 測試
  2. 瀏覽器訪問http://127.0.0.1:8080/index3,正確打印配置的值


redis.cache.commandTimeout=3000
redis.cache.expireSeconds=20
server.port=800
timeout=200


@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));
}
}
  1. 測試
  2. 在Apollo服務端修改timeout配置的值為300,發佈後,控制檯打印300


2.2.2.3 @ApolloJsonValue的使用

  1. 新增User如下:
Spring Boot 2.0 整合攜程Apollo配置中心

  1. 服務端新增配置
jsonBeanProperty=[ { "username": "john", "password": "1234" }, { "username": "simon", "password": "222132" } ]
  1. 客戶端獲取配置

//4. @ApolloJsonValue使用
@ApolloJsonValue("${jsonBeanProperty:[]}")
private List<User> anotherJsonBeans;
@RequestMapping("/index4")
public void hello4(){
anotherJsonBeans.forEach(item -> {
System.err.println(item.getUsername()+"--"+item.getPassword());
});
}
  1. 測試
  2. 瀏覽器訪問http://127.0.0.1:8080/index4,正確打印配置的值


源碼下載

https://github.com/simondongji/SpringCloudProject/tree/master/apollo

相關推薦

推薦中...