Nacos 之外,配置中心不可忽視的另一款 “神器”
“配置”的本質(zhì)是什么呢?
- 配置的表象,一個(gè)配置項(xiàng)可能是key-value,value可能是一個(gè)有限值的集合。
- 從我的理解來(lái)說(shuō),本質(zhì)上是因?yàn)槲覀內(nèi)祟悰](méi)有辦法掌控和預(yù)知一切,所以我們需要人為的預(yù)留一些線頭,以便撥弄這些線頭調(diào)整系統(tǒng)的飛行狀態(tài)。
所以我覺(jué)得配置中心是程序運(yùn)行時(shí)動(dòng)態(tài)調(diào)整行為能力的一種手段,而且這個(gè)是上到生產(chǎn),在運(yùn)行時(shí)想調(diào)整行為的幾乎唯一的一個(gè)手段。
1. 基本概念
由于Apollo 概念比較多,剛開(kāi)始使用比較復(fù)雜,最好先過(guò)一遍概念再動(dòng)手實(shí)踐嘗試使用。
1.1、背景
隨著程序功能的日益復(fù)雜,程序的配置日益增多,各種功能的開(kāi)關(guān)、參數(shù)的配置、服務(wù)器的地址……對(duì)程序配置的期望值也越來(lái)越高,配置修改后實(shí)時(shí)生效,灰度發(fā)布,分環(huán)境、分集群管理配置,完善的權(quán)限、審核機(jī)制…… 在這樣的大環(huán)境下,傳統(tǒng)的通過(guò)配置文件、數(shù)據(jù)庫(kù)等方式已經(jīng)越來(lái)越無(wú)法滿足開(kāi)發(fā)人員對(duì)配置管理的需求。因此 Apollo 配置中心應(yīng)運(yùn)而生!
1.2、簡(jiǎn)介
Apollo(阿波羅)是攜程框架部門研發(fā)的開(kāi)源配置管理中心,能夠集中化管理應(yīng)用不同環(huán)境、不同集群的配置,配置修改后能夠?qū)崟r(shí)推送到應(yīng)用端,并且具備規(guī)范的權(quán)限、流程治理等特性。
1.3、特點(diǎn)
- 部署簡(jiǎn)單
- 灰度發(fā)布
- 版本發(fā)布管理
- 提供開(kāi)放平臺(tái)API
- 客戶端配置信息監(jiān)控
- 提供Java和.Net原生客戶端
- 配置修改實(shí)時(shí)生效(熱發(fā)布)
- 權(quán)限管理、發(fā)布審核、操作審計(jì)
- 統(tǒng)一管理不同環(huán)境、不同集群的配置
1.4、基礎(chǔ)模型
如下即是 Apollo 的基礎(chǔ)模型:
(1)、用戶在配置中心對(duì)配置進(jìn)行修改并發(fā)布
(2)、配置中心通知Apollo客戶端有配置更新
(3)、Apollo客戶端從配置中心拉取最新的配置、更新本地配置并通知到應(yīng)用
圖片
1.5、Apollo 的四個(gè)維度
Apollo支持4個(gè)維度管理Key-Value格式的配置:
- application (應(yīng)用)
- environment (環(huán)境)
- cluster (集群)
- namespace (命名空間)
(1)application
- Apollo 客戶端在運(yùn)行時(shí)需要知道當(dāng)前應(yīng)用是誰(shuí),從而可以根據(jù)不同的應(yīng)用來(lái)獲取對(duì)應(yīng)應(yīng)用的配置。
- 每個(gè)應(yīng)用都需要有唯一的身份標(biāo)識(shí),可以在代碼中配置 app.id 參數(shù)來(lái)標(biāo)識(shí)當(dāng)前應(yīng)用,Apollo 會(huì)根據(jù)此指來(lái)辨別當(dāng)前應(yīng)用。
- 如果你近期準(zhǔn)備面試跳槽,建議在ddkk.com在線刷題,涵蓋 一萬(wàn)+ 道 Java 面試題,幾乎覆蓋了所有主流技術(shù)面試題,還有市面上最全的技術(shù)五百套,精品系列教程,免費(fèi)提供。
(2)environment
在實(shí)際開(kāi)發(fā)中,我們的應(yīng)用經(jīng)常要部署在不同的環(huán)境中,一般情況下分為開(kāi)發(fā)、測(cè)試、生產(chǎn)等等不同環(huán)境,不同環(huán)境中的配置也是不同的,在 Apollo 中默認(rèn)提供了四種環(huán)境:
- FAT(Feature Acceptance Test):功能測(cè)試環(huán)境
- UAT(User Acceptance Test):集成測(cè)試環(huán)境
- DEV(Develop):開(kāi)發(fā)環(huán)境
- PRO(Produce):生產(chǎn)環(huán)境
在程序中如果想指定使用哪個(gè)環(huán)境,可以配置變量 env 的值為對(duì)應(yīng)環(huán)境名稱即可。
(3)cluster
- 一個(gè)應(yīng)用下不同實(shí)例的分組,比如典型的可以按照數(shù)據(jù)中心分,把上海機(jī)房的應(yīng)用實(shí)例分為一個(gè)集群,把北京機(jī)房的應(yīng)用實(shí)例分為另一個(gè)集群。
- 對(duì)不同的集群,同一個(gè)配置可以有不一樣的值,比如說(shuō)上面所指的兩個(gè)北京、上海兩個(gè)機(jī)房設(shè)置兩個(gè)集群,兩個(gè)集群中都有 mysql 配置參數(shù),其中參數(shù)中配置的地址是不一樣的。
(4)namespace
一個(gè)應(yīng)用中不同配置的分組,可以簡(jiǎn)單地把 namespace 類比為不同的配置文件,不同類型的配置存放在不同的文件中,如數(shù)據(jù)庫(kù)配置文件,RPC 配置文件,應(yīng)用自身的配置文件等。
熟悉SpringBoot 的都知道,SpringBoot 項(xiàng)目都有一個(gè)默認(rèn)配置文件 application.yml,如果還想用多個(gè)配置,可以創(chuàng)建多個(gè)配置文件來(lái)存放不同的配置信息,通過(guò)指定 spring.profiles.active 參數(shù)指定應(yīng)用不同的配置文件。這里的 namespace 概念與其類似,將不同的配置放到不同的配置 namespace 中。
Namespace 分為兩種權(quán)限,分別為:
- public(公共的): public權(quán)限的 Namespace,能被任何應(yīng)用獲取。
- private(私有的): 只能被所屬的應(yīng)用獲取到。一個(gè)應(yīng)用嘗試獲取其它應(yīng)用 private 的 Namespace,Apollo 會(huì)報(bào) "404" 異常。
Namespace 分為三種類型,分別為:
- 私有類型: 私有類型的 Namespace 具有 private 權(quán)限。例如 application Namespace 為私有類型。
- 公共類型: 公共類型的 Namespace 具有 public 權(quán)限。公共類型的N amespace 相當(dāng)于游離于應(yīng)用之外的配置,且通過(guò) Namespace 的名稱去標(biāo)識(shí)公共 Namespace,所以公共的 Namespace 的名稱必須全局唯一。
- 如果你近期準(zhǔn)備面試跳槽,建議在ddkk.com在線刷題,涵蓋 一萬(wàn)+ 道 Java 面試題,幾乎覆蓋了所有主流技術(shù)面試題,還有市面上最全的技術(shù)五百套,精品系列教程,免費(fèi)提供。
- 關(guān)聯(lián)類型(繼承類型): 關(guān)聯(lián)類型又可稱為繼承類型,關(guān)聯(lián)類型具有 private 權(quán)限。關(guān)聯(lián)類型的 Namespace 繼承于公共類型的 Namespace,將里面的配置全部繼承,并且可以用于覆蓋公共 Namespace 的某些配置。
1.6、本地緩存
Apollo客戶端會(huì)把從服務(wù)端獲取到的配置在本地文件系統(tǒng)緩存一份,用于在遇到服務(wù)不可用,或網(wǎng)絡(luò)不通的時(shí)候,依然能從本地恢復(fù)配置,不影響應(yīng)用正常運(yùn)行。本地緩存路徑默認(rèn)位于以下路徑,所以請(qǐng)確保/opt/data或C:\opt\data\目錄存在,且應(yīng)用有讀寫權(quán)限。
- Mac/Linux: /opt/data/{appId}/config-cache
- Windows: C:\opt\data{appId}\config-cache
本地配置文件會(huì)以下面的文件名格式放置于本地緩存路徑下:
{appId}+{cluster}+{namespace}.properties
1.7、客戶端設(shè)計(jì)
圖片
上圖簡(jiǎn)要描述了Apollo客戶端的實(shí)現(xiàn)原理
- 客戶端和服務(wù)端保持了一個(gè)長(zhǎng)連接,從而能第一時(shí)間獲得配置更新的推送。
- 客戶端還會(huì)定時(shí)從 Apollo 配置中心服務(wù)端拉取應(yīng)用的最新配置。
- 這是一個(gè) fallback 機(jī)制,為了防止推送機(jī)制失效導(dǎo)致配置不更新
客戶端定時(shí)拉取會(huì)上報(bào)本地版本,所以一般情況下,對(duì)于定時(shí)拉取的操作,服務(wù)端都會(huì)返回 304 - Not Modified
定時(shí)頻率默認(rèn)為每 5 分鐘拉取一次,客戶端也可以通過(guò)在運(yùn)行時(shí)指定 apollo.refreshInterval 來(lái)覆蓋,單位為分鐘。
- 客戶端從 Apollo 配置中心服務(wù)端獲取到應(yīng)用的最新配置后,會(huì)保存在內(nèi)存中。
- 客戶端會(huì)把從服務(wù)端獲取到的配置在本地文件系統(tǒng)緩存一份 在遇到服務(wù)不可用,或網(wǎng)絡(luò)不通的時(shí)候,依然能從本地恢復(fù)配置。
- 應(yīng)用程序從 Apollo 客戶端獲取最新的配置、訂閱配置更新通知。
配置更新推送實(shí)現(xiàn)
前面提到了 Apollo 客戶端和服務(wù)端保持了一個(gè)長(zhǎng)連接,從而能第一時(shí)間獲得配置更新的推送。長(zhǎng)連接實(shí)際上我們是通過(guò) Http Long Polling 實(shí)現(xiàn)的,具體而言:
- 客戶端發(fā)起一個(gè) Http 請(qǐng)求到服務(wù)端
- 服務(wù)端會(huì)保持住這個(gè)連接 60 秒
- 如果在 60 秒內(nèi)有客戶端關(guān)心的配置變化,被保持住的客戶端請(qǐng)求會(huì)立即返回,并告知客戶端有配置變化的 namespace 信息,客戶端會(huì)據(jù)此拉取對(duì)應(yīng) namespace 的最新配置
如果在 60 秒內(nèi)沒(méi)有客戶端關(guān)心的配置變化,那么會(huì)返回 Http 狀態(tài)碼 304 給客戶端
- 客戶端在收到服務(wù)端請(qǐng)求后會(huì)立即重新發(fā)起連接,回到第一步
- 考慮到會(huì)有數(shù)萬(wàn)客戶端向服務(wù)端發(fā)起長(zhǎng)連,在服務(wù)端我們使用了 async servlet(Spring DeferredResult) 來(lái)服務(wù) Http Long Polling 請(qǐng)求。
1.8、總體設(shè)計(jì)
圖片
上圖簡(jiǎn)要描述了Apollo的總體設(shè)計(jì),我們可以從下往上看:
- Config Service 提供配置的讀取、推送等功能,服務(wù)對(duì)象是 Apollo 客戶端
- Admin Service 提供配置的修改、發(fā)布等功能,服務(wù)對(duì)象是 Apollo Portal(管理界面)
- Config Service 和 Admin Service 都是多實(shí)例、無(wú)狀態(tài)部署,所以需要將自己注冊(cè)到 Eureka 中并保持心跳
- 如果你近期準(zhǔn)備面試跳槽,建議在ddkk.com在線刷題,涵蓋 一萬(wàn)+ 道 Java 面試題,幾乎覆蓋了所有主流技術(shù)面試題,還有市面上最全的技術(shù)五百套,精品系列教程,免費(fèi)提供。
- 在 Eureka 之上我們架了一層 Meta Server 用于封裝Eureka的服務(wù)發(fā)現(xiàn)接口
- Client 通過(guò)域名訪問(wèn) Meta Server 獲取Config Service服務(wù)列表(IP+Port),而后直接通過(guò) IP+Port 訪問(wèn)服務(wù),同時(shí)在 Client 側(cè)會(huì)做 load balance 錯(cuò)誤重試
- Portal 通過(guò)域名訪問(wèn) Meta Server 獲取 Admin Service 服務(wù)列表(IP+Port),而后直接通過(guò) IP+Port 訪問(wèn)服務(wù),同時(shí)在 Portal 側(cè)會(huì)做 load balance、錯(cuò)誤重試
- 為了簡(jiǎn)化部署,我們實(shí)際上會(huì)把 Config Service、Eureka 和 Meta Server 三個(gè)邏輯角色部署在同一個(gè) JVM 進(jìn)程中
1.9、可用性考慮
配置中心作為基礎(chǔ)服務(wù),可用性要求非常高,下面的表格描述了不同場(chǎng)景下Apollo的可用性:
場(chǎng)景 | 影響 | 降級(jí) | 原因 |
某臺(tái) config service 下線 | 無(wú)影響 | Config service無(wú)狀態(tài),客戶端重連其它c(diǎn)onfig service | |
所有 config service 下線 | 客戶端無(wú)法讀取最新配置,Portal無(wú)影響 | 客戶端重啟時(shí),可以讀取本地緩存配置文件 | |
某臺(tái) admin service 下線 | 無(wú)影響 | Admin service無(wú)狀態(tài),Portal重連其它 admin service | |
所有 admin service 下線 | 客戶端無(wú)影響,portal無(wú)法更新配置 | ||
某臺(tái) portal 下線 | 無(wú)影響 | Portal域名通過(guò)slb綁定多臺(tái)服務(wù)器,重試后指向可用的服務(wù)器 | |
全部 portal 下線 | 客戶端無(wú)影響,portal無(wú)法更新配置 | ||
某個(gè)數(shù)據(jù)中心下線 | 無(wú)影響 | 多數(shù)據(jù)中心部署,數(shù)據(jù)完全同步,Meta Server/Portal 域名通過(guò) slb 自動(dòng)切換到其它存活的數(shù)據(jù)中心 |
2. Apollo 配置中心創(chuàng)建項(xiàng)目與配置
接下來(lái)我們將創(chuàng)建一個(gè) Apollo 的客戶端項(xiàng)目,引用 Apollo 來(lái)實(shí)現(xiàn)配置動(dòng)態(tài)更新,不過(guò)在此之前我們需要提前進(jìn)入 Apollo Portal 界面,在里面提前創(chuàng)建一個(gè)項(xiàng)目并在其配置一個(gè)參數(shù),方便后續(xù)客戶端引入該配置參數(shù),測(cè)試是否能動(dòng)態(tài)變化。
2.1、登錄 Apollo
我這里是部署到 Kubernetes 中,通過(guò) NodePort 方式暴露出一個(gè)端口,打開(kāi)這個(gè)地址登錄 Apollo:
- 用戶名:apollo
- 密 碼:admin
圖片
2.2、修改與增加部門數(shù)據(jù)
在登錄后創(chuàng)建項(xiàng)目時(shí),選擇部門默認(rèn)只能選擇 Apollo 自帶的 測(cè)試部門1與測(cè)試部門2兩個(gè)選項(xiàng)。
圖片
開(kāi)始這真讓人迷糊,原來(lái) Apoloo 沒(méi)有修改或新增部門信息的管理節(jié)目,只能通過(guò)修改數(shù)據(jù)庫(kù),來(lái)新增或者修改數(shù)據(jù),這里打開(kāi) Portal 對(duì)月的數(shù)據(jù)庫(kù)中的表 ApolloPortalDB 修改 key 為 organizations 的 value 的 json 數(shù)據(jù),改成自己對(duì)于的部門信息。
圖片
2.3、創(chuàng)建一個(gè)項(xiàng)目
修改完數(shù)據(jù)庫(kù)部門信息后,重新登錄 Apollo Portal,然后創(chuàng)建項(xiàng)目,這時(shí)候選擇部門可以看到已經(jīng)變成我們自己修改后的部門信息了,選擇我們自定義部門,然后設(shè)置應(yīng)用 ID 為 apollo-test,應(yīng)用名為 apollo-demo 。
圖片
創(chuàng)建完成后進(jìn)入配置管理界面。
圖片
2.4、創(chuàng)建一個(gè)配置參數(shù)
創(chuàng)建一個(gè)配置參數(shù),方便后續(xù) Apollo 客戶端項(xiàng)目引入該參數(shù),進(jìn)行動(dòng)態(tài)配置測(cè)試。
圖片
設(shè)置key 為 test value 為 123456 然后設(shè)置一個(gè)備注,保存。
圖片
創(chuàng)建完成后可以看到配置管理節(jié)目新增了一條配置。
圖片
接下來(lái)我們將此配置通過(guò)發(fā)布按鈕,進(jìn)行發(fā)布。
圖片
3. 創(chuàng)建 Apollo 客戶端測(cè)試項(xiàng)目
這里創(chuàng)建一個(gè) SpringBoot 項(xiàng)目,引入 Apollo 客戶端來(lái)來(lái)實(shí)現(xiàn)與 Apollo 配置中心服務(wù)端交互。
3.1、Mavne 添加 Apollo 依賴
<?xml versinotallow="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
</parent>
<groupId>club.mydlq</groupId>
<artifactId>apollo-demo</artifactId>
<version>0.0.1</version>
<name>apollo-demo</name>
<description>Apollo Demo</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.2、配置文件添加參數(shù)
在 application.yml 配置文件中添加下面參數(shù),這里簡(jiǎn)單介紹下 Apollo 參數(shù)作用:
- apollo.meta: Apollo 配置中心地址。
- apollo.cluster: 指定使用某個(gè)集群下的配置。
- apollo.bootstrap.enabled: 是否開(kāi)啟 Apollo。
- apollo.bootstrap.namespaces : 指定使用哪個(gè) Namespace 的配置,默認(rèn) application。
- apollo.cacheDir=/opt/data/some-cache-dir: 為了防止配置中心無(wú)法連接等問(wèn)題,Apollo 會(huì)自動(dòng)將配置本地緩存一份。
- apollo.autoUpdateInjectedSpringProperties: Spring應(yīng)用通常會(huì)使用 Placeholder 來(lái)注入配置,如${someKey:someDefaultValue},冒號(hào)前面的是 key,冒號(hào)后面的是默認(rèn)值。如果想關(guān)閉 placeholder 在運(yùn)行時(shí)自動(dòng)更新功能,可以設(shè)置為 false。
- apollo.bootstrap.eagerLoad.enabled : 將 Apollo 加載提到初始化日志系統(tǒng)之前,如果設(shè)置為 false,那么將打印出 Apollo 的日志信息,但是由于打印 Apollo 日志信息需要日志先啟動(dòng),啟動(dòng)后無(wú)法對(duì)日志配置進(jìn)行修改,所以 Apollo 不能管理應(yīng)用的日志配置,如果設(shè)置為 true,那么 Apollo 可以管理日志的配置,但是不能打印出 Apollo 的日志信息。
#應(yīng)用配置
server:
port: 8080
spring:
application:
name: apollo-demo
#Apollo 配置
app:
id: apollo-test #應(yīng)用ID
apollo:
cacheDir: /opt/data/ #配置本地配置緩存目錄
cluster: default #指定使用哪個(gè)集群的配置
meta: http://192.168.2.11:30002 #DEV環(huán)境配置中心地址
autoUpdateInjectedSpringProperties: true #是否開(kāi)啟 Spring 參數(shù)自動(dòng)更新
bootstrap:
enabled: true #是否開(kāi)啟 Apollo
namespaces: application #設(shè)置 Namespace
eagerLoad:
enabled: false #將 Apollo 加載提到初始化日志系統(tǒng)之前
3.3、創(chuàng)建測(cè)試 Controller 類
寫一個(gè) Controller 類來(lái)輸出 test 變量的值,使用了 Spring 的 @Value 注解,用于讀取配置文件中的變量的值,這里來(lái)測(cè)試該值,項(xiàng)目啟動(dòng)后讀取到的變量的值是設(shè)置在 application 配置文件中的默認(rèn)值,還是遠(yuǎn)程 Apollo 中的值,如果是 Apollo 中配置的值,那么再測(cè)試在 Apollo 配置中心中改變?cè)撟兞康闹岛?,這里是否會(huì)產(chǎn)生變化。
@RestController
public class TestController {
@Value("${test:默認(rèn)值}")
private String test;
@GetMapping("/test")
public String test(){
return "test的值為:" + test;
}
}
3.4、創(chuàng)建啟動(dòng)類
SpringBoot 項(xiàng)目啟動(dòng)類。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3.5、JVM 啟動(dòng)參數(shù)添加啟動(dòng)參數(shù)
由于本人的 Apollo 是部署在 Kubernetes 環(huán)境中的,JVM 參數(shù)中必須添加兩個(gè)變量:
- env: 應(yīng)用使用 Apollo 哪個(gè)環(huán)境,例如設(shè)置為 DEV 就是指定使用開(kāi)發(fā)環(huán)境,如果設(shè)置為 PRO 就是制定使用生產(chǎn)環(huán)境。
- apollo.configService: 指定配置中心的地址,跳過(guò) meta 的配置,在測(cè)試時(shí)指定 meta 地址無(wú)效果。如果 Apollo 是部署在 Kubernetes 中,則必須設(shè)置該參數(shù)為配置中心地址,如果 Apollo 不是在 Kubernetes 環(huán)境中,可以不設(shè)置此參數(shù),只設(shè)置 meta 參數(shù)即可。一般情況下,configService 和 meta 值一致。
如果是在 Idea 中啟動(dòng),可以配置啟動(dòng)參數(shù),加上:
-Dapollo.cnotallow=http://192.168.2.11:30002 -Denv=DEV
如果是java 命令啟動(dòng)程序,需要 JVM 加上:
$ java -Dapollo.cnotallow=http://192.168.2.11:30002 -Denv=DEV -jar apollo-demo.jar
注意:上面 env 指定的環(huán)境,要和 apollo.meta 指定 Config 地址的環(huán)境一致,例如 -Denv=DEV 即使用開(kāi)發(fā)環(huán)境,那么 apollo.meta=http://xxx.xxx.xxx:8080 這個(gè)url 的 Config 也是開(kāi)發(fā)環(huán)境下的配置中心服務(wù),而不能是 PRO 或者其它環(huán)境下的配置中心。
4. 啟動(dòng)項(xiàng)目進(jìn)行測(cè)試
4.1、測(cè)試是否能夠獲取 Apollo 中設(shè)置的值
啟動(dòng)上面的測(cè)試用例,然后輸入地址 http://localhost:8080/test 查看:
test的值為:123456
可以看到使用的是 Apollo 中配置的 test 參數(shù)的值 123456,而不是默認(rèn)的值。
4.2、測(cè)試當(dāng) Apollo 中修改參數(shù)值后客戶端是否能及時(shí)刷新
修改Apollo 配置中心參數(shù) test 值為 666666 ,然后再次發(fā)布。
圖片
發(fā)布完成后再次輸入地址 http://localhost:8080/test 查看:
test的值為:666666
可以看到示例應(yīng)用中的值已經(jīng)改變?yōu)樽钚碌闹怠?/p>
4.3、測(cè)試當(dāng) Apollo 執(zhí)行配置回滾操作時(shí)客戶端是否能及時(shí)改變
圖片
回滾完成后狀態(tài)將變?yōu)槲窗l(fā)布狀態(tài),則時(shí)候輸入地址 http://localhost:8080/test 查看:
test的值為:123456
可以看到已經(jīng)回滾到之前的 test 配置的值了。
4.4、測(cè)試當(dāng)不能訪問(wèn) Apollo 時(shí)客戶端的變化
這里我們將 JVM 參數(shù)中 Apollo 配置中心地址故意改錯(cuò):
-Dapollo.cnotallow=http://192.168.2.100:30002 -Denv=DEV
然后輸入地址 http://localhost:8080/test 可以看到值為:
test的值為:123456
可以看到顯示的值并不是我們定義的默認(rèn)值,而還是 Apollo 配置中心配置的 test 參數(shù)的值。考慮到由于 Apollo 會(huì)在本地將配置緩存一份,出現(xiàn)上面原因,估計(jì)是緩存生效。當(dāng)客戶端不能連接到 Apollo 配置中心時(shí)候,默認(rèn)使用本地緩存文件中的配置。
如果你近期準(zhǔn)備面試跳槽,建議在ddkk.com在線刷題,涵蓋 一萬(wàn)+ 道 Java 面試題,幾乎覆蓋了所有主流技術(shù)面試題,還有市面上最全的技術(shù)五百套,精品系列教程,免費(fèi)提供。
上面我們配置了本地緩存配置文件存放地址為 "/opt/data/" ,接下來(lái)進(jìn)入緩存目錄,找到對(duì)應(yīng)的緩存配置文件,刪除緩存配置文件后,重啟應(yīng)用,再次輸入地址查看:
test的值為:默認(rèn)值
刪除緩存配置文件后,可以看到輸出的值為自己定義的默認(rèn)值。
4.5、測(cè)試當(dāng) Apollo 中將參數(shù)刪除后客戶端的變化
這里我們進(jìn)入 Apollo 配置中心,刪除之前創(chuàng)建的 test 參數(shù),然后發(fā)布。
圖片
然后,再次打開(kāi)地址 http://localhost:8080/test 查看:
test的值為:默認(rèn)值
可以看到顯示的是應(yīng)用程序中設(shè)置的默認(rèn)值。
5. 對(duì) Apollo 的 Cluster、Namespace 進(jìn)行探究
在Apollo 中,配置可以根據(jù)不同的環(huán)境劃分為 Dev(開(kāi)發(fā))、Prod(生產(chǎn)) 等環(huán)境,又能根據(jù)區(qū)域劃分為不同的 Cluster(集群),還能根據(jù)配置參數(shù)作用功能的不同劃分為不同的 Namespace(命名空間),這里探究下,如何使用上述能力。
5.1、不同環(huán)境下的配置
(1)Apollo 配置中心 PRO 環(huán)境添加參數(shù)
打開(kāi)Apollo 配置中心,環(huán)境列表點(diǎn)擊 PRO 環(huán)境,然后新增一條配置,和之前例子中參數(shù)保持一致,都為 test 參數(shù),創(chuàng)建完成后發(fā)布。
圖片
然后修改上面的示例項(xiàng)目,將配置參數(shù)指定為 PRO 環(huán)境:
(2)示例項(xiàng)目修改 application.yml 配置文件
把a(bǔ)pollo.meta 參數(shù)改成 RPO 的配置中心地址
......
apollo:
meta: http://192.168.2.11:30005 #RPO環(huán)境配置中心地址
......
(3)示例項(xiàng)目修改 JVM 參數(shù)
把a(bǔ)pollo.configService 參數(shù)改成 PRO 配置中心地址,env 參數(shù)的值改為 PRO。
-Dapollo.cnotallow=http://192.168.2.11:30005 -Denv=PRO
(4)啟動(dòng)示例項(xiàng)目觀察結(jié)果
啟動(dòng)示例項(xiàng)目,然后接著輸入地址 http://localhost:8080/test 查看信息:
test的值為:abcdefg
可以看到已經(jīng)改成生成環(huán)境配置,所以在實(shí)際項(xiàng)目中,如果要更換環(huán)境,需要修改 JVM 參數(shù) env(如果 Apollo 部署在 Kubernetes 環(huán)境中,還需要修改 apollo.configService 參數(shù)),和修改 application.yml 配置文件的參數(shù) apollo.meta 值。
5.2、不同集群下的配置
(1)創(chuàng)建兩個(gè)集群
例如在開(kāi)發(fā)過(guò)程中,經(jīng)常要將應(yīng)用部署到不同的機(jī)房,這里分別創(chuàng)建 beijing、shanghai 兩個(gè)集群。
圖片
圖片
圖片
(2)兩個(gè)集群都配置同樣的參數(shù)不同的值
在兩個(gè)集群 beijing 與 shanghai 中,都統(tǒng)一配置參數(shù) test,并且設(shè)置不同的值。
圖片
圖片
(3)示例項(xiàng)目 application.yml 修改集群配置參數(shù),并啟動(dòng)項(xiàng)目觀察結(jié)果
指定集群為 beijing:
......
apollo:
cluster: beijing #指定使用 beijing 集群
......
啟動(dòng)示例項(xiàng)目,然后接著輸入地址 http://localhost:8080/test 查看信息:
test的值為:Cluster-BeiJing
可以看到用的是 beijing 集群的配置。
指定集群為 shanghai:
......
apollo:
cluster: shanghai #指定使用 shanghai 集群
......
啟動(dòng)示例項(xiàng)目,然后接著輸入地址 http://localhost:8080/test 查看信息:
test的值為:Cluster-ShangHai
可以看到用的是 shanghai 集群的配置
5.3、不同命名空間下的配置
(1)創(chuàng)建兩個(gè)命名空間
命名空間有兩種,一種是 public(公開(kāi)),一種是 private 私有,公開(kāi)命名空間所有項(xiàng)目都能讀取配置信息,而私有的只能 app.id 值屬于該應(yīng)用的才能讀取配置。
這里創(chuàng)建 dev-1 與 dev-2 兩個(gè)私有的命名空間,用于測(cè)試。
圖片
圖片
圖片
(2)兩個(gè)集群都配置同樣的參數(shù)不同的值
在兩個(gè)命名空間中,都統(tǒng)一配置參數(shù) test,并且設(shè)置不同的值,設(shè)置完后發(fā)布。
圖片
(3)示例項(xiàng)目 application.yml 修改命名空間配置參數(shù),并啟動(dòng)項(xiàng)目觀察結(jié)果
指定命名空間為 dev-1:
......
apollo:
bootstrap:
namespaces: dev-1 #設(shè)置 dev-1 命名空間
......
啟動(dòng)示例項(xiàng)目,然后接著輸入地址 http://localhost:8080/test 查看信息:
test的值為:dev-1 Namespace
可以看到用的是 dev-1 命名空間的配置。
指定命名空間為 dev-2:
......
apollo:
bootstrap:
namespaces: dev-2 #設(shè)置 dev-1 命名空間
......
YAML
啟動(dòng)示例項(xiàng)目,然后接著輸入地址 http://localhost:8080/test 查看信息:
test的值為:dev-2 Namespace
HTML
可以看到用的是 dev-2 命名空間的配置
6. Kubernetes 的 SpringBoot 應(yīng)用使用 Apollo 配置中心
本人的Apollo 和 SpringBoot 應(yīng)用一般都是基于 Kubernetes 部署的,所以這里簡(jiǎn)單介紹下,如何在 Kubernetes 環(huán)境下部署 SpringBoot 應(yīng)用且使用 Apollo 作為配置中心。
這里項(xiàng)目依舊使用上面的示例,不過(guò)首先要將其編譯成 Docker 鏡像,方便后續(xù)部署到 Kubernetes 環(huán)境下。
6.1、構(gòu)建 Docker 鏡像
(1)執(zhí)行 Maven 編譯
首先執(zhí)行 Maven 命令,將項(xiàng)目編譯成一個(gè)可執(zhí)行 JAR。
$ mvn clean install
BASH
(2)備 Dockerfile
創(chuàng)建構(gòu)建 Docker 鏡像需要的 Dockerfile 文件,將 Maven 編譯的 JAR 復(fù)制到鏡像內(nèi)部,然后設(shè)置兩個(gè)變量,分別是:
如果你近期準(zhǔn)備面試跳槽,建議在ddkk.com在線刷題,涵蓋 一萬(wàn)+ 道 Java 面試題,幾乎覆蓋了所有主流技術(shù)面試題,還有市面上最全的技術(shù)五百套,精品系列教程,免費(fèi)提供。
- JAVA_OPTS: Java JVM 啟動(dòng)參數(shù)變量,這里需要在這里加一個(gè)時(shí)區(qū)參數(shù)。
- APP_OPTS: Spring 容器啟動(dòng)參數(shù)變量,方便后續(xù)操作時(shí)能通過(guò)此變量配置 Spring 參數(shù)。
Dockerfile:
FROM openjdk:8u222-jre-slim
VOLUME /tmp
ADD target/*.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timeznotallow=Asia/Shanghai"
ENV APP_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
(3)構(gòu)建 Docker 鏡像
執(zhí)行Docker Build 命令構(gòu)建 Docker 鏡像。
$ docker build -t mydlqclub/springboot-apollo:0.0.1 .
BASH
6.2、Kubernetes 部署示例應(yīng)用
(1)創(chuàng)建 SpringBoot 且使用 Apollo 配置中心的 Kubernetes 部署文件
這里創(chuàng)建 Kubernetes 下的 SpringBoot 部署文件 apollo-demo-example.yaml。在之前 Dockerfile 中設(shè)置了兩個(gè)環(huán)境變量,JAVA_OPTS 與 APP_OPTS。其中 JAVA_OPTS 變量的值將會(huì)作為 JVM 啟動(dòng)參數(shù),APP_OPTS 變量的值將會(huì)作為應(yīng)用的配置參數(shù)。所以,這里我們將 Apollo 配置參數(shù)放置到變量中,這樣一來(lái)就可以方便修改與維護(hù) Apollo 的配置信息。
在下面配置的環(huán)境變量參數(shù)中,設(shè)置的配置中心地址為 http://service-apollo-config-server-dev.mydlqclub:8080,這是因?yàn)?Apollo 部署在 K8S 環(huán)境中,且可以使用域名方式訪問(wèn),service-apollo-config-server-dev 是應(yīng)用的 Service 名稱,mydlqcloud 是 K8S 下的 Namespace 名稱。
springboot-apollo.yaml
apiVersion: v1
kind: Service
metadata:
name: springboot-apollo
spec:
type: NodePort
ports:
- name: server
nodePort: 31080
port: 8080
targetPort: 8080
- name: management
nodePort: 31081
port: 8081
targetPort: 8081
selector:
app: springboot-apollo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: springboot-apollo
labels:
app: springboot-apollo
spec:
replicas: 1
selector:
matchLabels:
app: springboot-apollo
template:
metadata:
name: springboot-apollo
labels:
app: springboot-apollo
spec:
restartPolicy: Always
containers:
- name: springboot-apollo
image: mydlqclub/springboot-apollo:0.0.1
imagePullPolicy: Always
ports:
- containerPort: 8080
name: server
env:
- name: JAVA_OPTS
value: "-Denv=DEV"
##注意修改此處的 mydlqcloud 為你自己的 Namespace 名稱
- name: APP_OPTS
value: "
--app.id=apollo-demo
--apollo.bootstrap.enabled=true
--apollo.bootstrap.eagerLoad.enabled=false
--apollo.cacheDir=/opt/data/
--apollo.cluster=default
--apollo.bootstrap.namespaces=application
--apollo.autoUpdateInjectedSpringProperties=true
--apollo.meta=http://service-apollo-config-server-dev.mydlqcloud:8080
"
resources:
limits:
memory: 1000Mi
cpu: 1000m
requests:
memory: 500Mi
cpu: 500m
(2)部署 SpringBoot 應(yīng)用到 Kubernetes
-n:創(chuàng)建應(yīng)用到指定的 Namespace 中。
$ kubectl apply -f springboot-apollo.yaml -n mydlqcloud
BASH
6.3、測(cè)試部署的應(yīng)用接口
上面的應(yīng)用配置了 NodePort 端口,可以通過(guò)此端口訪問(wèn) Kubernetes 集群內(nèi)的應(yīng)用接口,本人 Kubernetes 集群地址為 192.168.2.11 且 NodePort 端口為 31081,所以瀏覽器訪問(wèn)地址 http://192.168.2.11:31081/test 來(lái)測(cè)試接口,顯示:
test的值為:123456
可以看到能通過(guò) Apollo 獲取參數(shù)值,此文章到此結(jié)束。