2020年了還不知道配置中心?

Hi嘲驾,好久不見淌哟,我是你們的walking****,在這個(gè)高燃BGM下又和大家見面了??辽故。今天分享一個(gè)分布式徒仓、微服務(wù)架構(gòu)中重要的一個(gè)組件:配置中心。

也許你們現(xiàn)在的項(xiàng)目不是分布式誊垢、微服務(wù)架構(gòu)掉弛,沒(méi)有用到配置中心,也沒(méi)聽說(shuō)過(guò)配置中心喂走,對(duì)它完全很陌生殃饿,那你就很有必要閱讀本文了。

本文將從

1)什么是配置芋肠、什么是配置中心以及配置中心的誕生講起乎芳,

2)然后簡(jiǎn)單介紹幾個(gè)不錯(cuò)的開源配置中心產(chǎn)品,

3)接著會(huì)重點(diǎn)介紹攜程開源的分布式配置中心Apollo的架構(gòu)以及基本的搭建與使用业栅。

好了廢話不多說(shuō)秒咐,開始...????

什么是配置谬晕?

眾所周知碘裕,應(yīng)用程序在啟動(dòng)和運(yùn)行的時(shí)候會(huì)去讀取一些「配置信息」,比如:數(shù)據(jù)庫(kù)連接參數(shù)攒钳、啟動(dòng)參數(shù)帮孔、接口的超時(shí)時(shí)間、應(yīng)用程序的端口等不撑∥木ぃ「配置」,基本上伴隨著應(yīng)用程序的整個(gè)生命周期焕檬。

不知道大家有沒(méi)有注意姆坚,配置其實(shí)它有一些比較明顯的特點(diǎn),如下:

1实愚、獨(dú)立于程序的只讀變量

1)配置是獨(dú)立于應(yīng)用程序的兼呵,并且同一個(gè)程序在不同的配置下會(huì)有不同的行為兔辅;

2)其次,配置對(duì)于程序是只讀的击喂,程序通過(guò)讀取配置來(lái)改變自己的行為维苔,程序不應(yīng)該去改變配置

2、伴隨應(yīng)用的整個(gè)生命周期

1)配置貫穿于應(yīng)用的整個(gè)生命周期懂昂,包括啟動(dòng)和運(yùn)行介时。應(yīng)用在啟動(dòng)時(shí)通過(guò)讀取配置來(lái)初始化,在運(yùn)行時(shí)根據(jù)配置調(diào)整行為凌彬。比如:?jiǎn)?dòng)時(shí)需要讀取服務(wù)的端口號(hào)沸柔、系統(tǒng)在運(yùn)行過(guò)程中需要讀取定時(shí)策略執(zhí)行定時(shí)任務(wù)、根據(jù)配置調(diào)整日志級(jí)別等饿序。

3勉失、多種加載方式

1)常見的加載方式有程序內(nèi)部硬編碼、配置文件原探、環(huán)境變量乱凿、啟動(dòng)參數(shù)、基于數(shù)據(jù)庫(kù)等咽弦,最常用的是配置文件和環(huán)境變量這兩種方式徒蟆。

4、需要治理

1)權(quán)限控制:由于配置能改變程序的行為型型,不正確的配置甚至?xí)斐蔀?zāi)難段审,所以對(duì)配置的修改必須有比較完善的權(quán)限控制體系來(lái)治理;

2)對(duì)不同環(huán)境闹蒜、集群進(jìn)行配置管理:同一個(gè)程序在不同的環(huán)境(開發(fā)寺枉,測(cè)試,預(yù)生產(chǎn)绷落、生產(chǎn))姥闪、不同的集群(如不同的數(shù)據(jù)中心、服務(wù)器在全國(guó)很多地方都有機(jī)房部署集群的情況)經(jīng)常需要有不同的配置砌烁,所以需要有完善的環(huán)境筐喳、集群配置管理的能力。

5函喉、支持持久化

1)配置信息需要支持持久化避归,永久保存,重啟后依然能夠找到之前的配置管呵,配置一旦生成就永久存在除非人為的刪除梳毙。

我們最常用的就是在項(xiàng)目的resources下創(chuàng)建各種properties文件放我們的各種配置

配置中心的誕生

配置中心的誕生和項(xiàng)目架構(gòu)的演進(jìn)有著密切的聯(lián)系。傳統(tǒng)單體應(yīng)用存在一些潛在缺陷捐下,如隨著規(guī)模的擴(kuò)大账锹,部署效率降低堂氯,團(tuán)隊(duì)協(xié)作效率差,系統(tǒng)可靠性變差牌废,維護(hù)困難咽白,新功能上線周期長(zhǎng)等鸟缕,所以迫切需要一種新的架構(gòu)去解決這些問(wèn)題侵贵,而微服務(wù)( microservices )架構(gòu)正是當(dāng)下一種流行的解決方案缘薛。

不過(guò),解決一個(gè)問(wèn)題的同時(shí)仪或,往往會(huì)面臨很多新的問(wèn)題,所以微服務(wù)化的過(guò)程中伴隨著很多的挑戰(zhàn)士骤,其中一個(gè)挑戰(zhàn)就是有關(guān)服務(wù)(應(yīng)用)配置的范删。

1)當(dāng)系統(tǒng)從一個(gè)單體應(yīng)用,被拆分成分布式系統(tǒng)上一個(gè)個(gè)服務(wù)節(jié)點(diǎn)后敦间,配置文件也必須跟著遷移(分割)瓶逃,這樣配置就分散了束铭,各個(gè)服務(wù)都有自己的配置廓块,隨著項(xiàng)目需求的不斷壯大發(fā)展,配置會(huì)越來(lái)越多契沫,到最后繁瑣的配置文件會(huì)讓你越來(lái)越崩潰带猴,稍不注意出個(gè)錯(cuò)配置錯(cuò)了就得修改配置重新打包部署,特別麻煩懈万。

2)在集群部署的情況下拴清,如果新版本的配置會(huì)給系統(tǒng)帶來(lái)很大的影響靶病,我們往往會(huì)選擇灰度發(fā)布,即先發(fā)布部分服務(wù)器口予,進(jìn)行測(cè)試娄周,穩(wěn)定后再將配置同步到所有服務(wù)器,如果說(shuō)還用傳統(tǒng)的方式沪停,那么我們就需要將配置文件一個(gè)個(gè)的修改然后重啟服務(wù)煤辨,雖然不需要我們開發(fā)自己去做,有運(yùn)維木张,那也挺煩人的众辨,運(yùn)維發(fā)布完了,我們還得檢查他改的是不是正確舷礼,費(fèi)時(shí)費(fèi)力鹃彻。

3)而且在系統(tǒng)不斷的迭代的過(guò)程中有些配置在多個(gè)服務(wù)之間都是相同或相近的,就會(huì)有很大的冗余妻献。

所以在分布式蛛株、微服務(wù)這種大環(huán)境下,傳統(tǒng)的項(xiàng)目配置方式的弊端就慢慢的凸顯出來(lái)了育拨,這個(gè)問(wèn)題變得非常棘手泳挥,亟待一種管理配置、治理配置的解決方案至朗。這時(shí)屉符,配置中心就應(yīng)運(yùn)而生了。

什么是配置中心

配置中心锹引,顧名思義矗钟,將配置中心化,說(shuō)白了就是將配置從應(yīng)用中抽取出來(lái)嫌变,統(tǒng)一管理吨艇,優(yōu)雅的解決了配置的動(dòng)態(tài)變更、權(quán)限管理腾啥、持久化东涡、運(yùn)維成本等問(wèn)題。應(yīng)用程序自身只是從配置中心拿到自己想要的配置倘待,既不需要去添加管理配置的接口疮跑,也不需要自己去實(shí)現(xiàn)配置的持久化,更不需要去關(guān)心配置何時(shí)變化凸舵。配置與應(yīng)用程序隔離開祖娘,單獨(dú)管理配置。

總得來(lái)說(shuō)啊奄,配置中心就是一種統(tǒng)一管理各種應(yīng)用配置的基礎(chǔ)服務(wù)組件渐苏。

在系統(tǒng)架構(gòu)中掀潮,配置中心是整個(gè)微服務(wù)基礎(chǔ)架構(gòu)體系中的一個(gè)組件,如下圖琼富,它的功能看上去并不起眼仪吧,無(wú)非就是配置的管理和存取,但它是整個(gè)微服務(wù)架構(gòu)中不可或缺的一環(huán)鞠眉。

image

集中管理配置邑商,那么就要將應(yīng)用的配置作為一個(gè)單獨(dú)的服務(wù)抽離出來(lái)了,同理也需要解決新的問(wèn)題凡蚜,比如:版本管理(為了支持回滾)人断,權(quán)限管理等。

總結(jié)一下朝蜘,在傳統(tǒng)巨型單體應(yīng)用紛紛轉(zhuǎn)向細(xì)粒度微服務(wù)架構(gòu)的歷史進(jìn)程中恶迈,配置中心是微服務(wù)化不可缺少的一個(gè)系統(tǒng)組件,在這種背景下中心化的配置服務(wù)即配置中心應(yīng)運(yùn)而生谱醇,一個(gè)合格的配置中心需要滿足一下功能:

  • 對(duì)配置項(xiàng)的讀取和修改提供簡(jiǎn)單易用的API和操作界面

  • 添加新配置要夠簡(jiǎn)單暇仲、直接、方便

  • 支持不同管理員對(duì)配置的修改的不同權(quán)限副渴,以把控風(fēng)險(xiǎn)

  • 可以查看配置修改的歷史記錄奈附,以便回滾

  • 不同部署環(huán)境相互隔離,互不影響

主流配置中心簡(jiǎn)介

目前市面上用的比較多的配置中心有:(按開源時(shí)間排序)

簡(jiǎn)介

1煮剧、Disconf

2014年7月百度開源的配置管理中心斥滤,專注于各種「分布式系統(tǒng)配置管理」的「通用組件」和「通用平臺(tái)」, 提供統(tǒng)一的「配置管理服務(wù)」。目前已經(jīng)不再維護(hù)更新勉盅。

https://github.com/knightliao/disconf

2佑颇、Spring Cloud Config

2014年9月開源,Spring Cloud 生態(tài)組件草娜,可以和Spring Cloud體系無(wú)縫整合挑胸。

https://github.com/spring-cloud/spring-cloud-config

3、Apollo

2016年5月宰闰,攜程開源的配置管理中心茬贵,能夠集中化管理應(yīng)用不同環(huán)境、不同集群的配置移袍,配置修改后能夠?qū)崟r(shí)推送到應(yīng)用端解藻,并且具備規(guī)范的權(quán)限、流程治理等特性咐容,適用于微服務(wù)配置管理場(chǎng)景舆逃。

https://github.com/ctripcorp/apollo

4蚂维、Nacos

2018年6月戳粒,阿里開源的配置中心路狮,也可以做DNS和RPC的服務(wù)發(fā)現(xiàn)。

https://github.com/alibaba/nacos

功能特性對(duì)比

由于Disconf不再維護(hù)蔚约,下面主要對(duì)比一下Spring Cloud Config奄妨、Apollo和Nacos。


image.png

總的來(lái)看苹祟,Apollo和Nacos相對(duì)于Spring Cloud Config的生態(tài)支持更廣砸抛,在配置管理流程上做的更好。Apollo相對(duì)于Nacos在配置管理做的更加全面树枫,Nacos則使用起來(lái)相對(duì)比較簡(jiǎn)潔直焙,在對(duì)性能要求比較高的大規(guī)模場(chǎng)景更適合。但對(duì)于一個(gè)開源項(xiàng)目的選型砂轻,項(xiàng)目上的人力投入(迭代進(jìn)度奔誓、文檔的完整性)、社區(qū)的活躍度(issue的數(shù)量和解決速度搔涝、Contributor數(shù)量厨喂、社群的交流頻次等),這些因素也比較關(guān)鍵庄呈,考慮到Nacos開源時(shí)間不長(zhǎng)和社區(qū)活躍度蜕煌,所以從目前來(lái)看Apollo應(yīng)該是最合適的配置中心選型。

Apollo

Apollo特性

基于配置的特殊性诬留,所以Apollo從設(shè)計(jì)之初就立志于成為一個(gè)有治理能力的配置發(fā)布平臺(tái)斜纪,目前提供了以下的特性:

1、統(tǒng)一管理不同環(huán)境文兑、不同集群的配置

  • Apollo提供了一個(gè)統(tǒng)一界面集中式管理不同環(huán)境(environment)傀广、不同集群(cluster)、不同命名空間(namespace)的配置彩届。

  • 同一份代碼部署在不同的集群伪冰,可以有不同的配置,比如zookeeper的地址等

  • 通過(guò)命名空間(namespace)可以很方便地支持多個(gè)不同應(yīng)用共享同一份配置樟蠕,同時(shí)還允許應(yīng)用對(duì)共享的配置進(jìn)行覆蓋

2贮聂、配置修改實(shí)時(shí)生效(熱發(fā)布)

  • 用戶在Apollo修改完配置并發(fā)布后,客戶端能實(shí)時(shí)(1秒)接收到最新的配置寨辩,并通知到應(yīng)用程序

3吓懈、版本發(fā)布管理

  • 所有的配置發(fā)布都有版本概念,從而可以方便地支持配置的回滾

4靡狞、灰度發(fā)布

  • 支持配置的灰度發(fā)布耻警,比如點(diǎn)了發(fā)布后,只對(duì)部分應(yīng)用實(shí)例生效,等觀察一段時(shí)間沒(méi)問(wèn)題后再推給所有應(yīng)用實(shí)例

5甘穿、權(quán)限管理腮恩、發(fā)布審核、操作審計(jì)

  • 應(yīng)用和配置的管理都有完善的權(quán)限管理機(jī)制温兼,對(duì)配置的管理還分為了編輯和發(fā)布兩個(gè)環(huán)節(jié)秸滴,從而減少人為的錯(cuò)誤。

  • 所有的操作都有審計(jì)日志募判,可以方便地追蹤問(wèn)題

6荡含、客戶端配置信息監(jiān)控

  • 可以在界面上方便地看到配置在被哪些實(shí)例使用

7、提供Java和.Net原生客戶端

  • 提供了Java和.Net的原生客戶端届垫,方便應(yīng)用集成

  • 支持Spring Placeholder, Annotation和Spring Boot的ConfigurationProperties释液,方便應(yīng)用使用(需要Spring 3.1.1+)

  • 同時(shí)提供了Http接口,非Java和.Net應(yīng)用也可以方便地使用

8装处、提供開放平臺(tái)API

  • Apollo自身提供了比較完善的統(tǒng)一配置管理界面均澳,支持多環(huán)境、多數(shù)據(jù)中心配置管理符衔、權(quán)限找前、流程治理等特性。不過(guò)Apollo出于通用性考慮判族,不會(huì)對(duì)配置的修改做過(guò)多限制躺盛,只要符合基本的格式就能保存,不會(huì)針對(duì)不同的配置值進(jìn)行針對(duì)性的校驗(yàn)形帮,如數(shù)據(jù)庫(kù)用戶名槽惫、密碼,Redis服務(wù)地址等

  • 對(duì)于這類應(yīng)用配置辩撑,Apollo支持應(yīng)用方通過(guò)開放平臺(tái)API在Apollo進(jìn)行配置的修改和發(fā)布界斜,并且具備完善的授權(quán)和權(quán)限控制

執(zhí)行流程

先來(lái)看一個(gè)簡(jiǎn)單的工作流程圖,如下:

image

操作流程如下:

1合冀、管理員通過(guò)可視化操作界面在Apollo配置中心修改各薇、發(fā)布配置

2、應(yīng)用程序通過(guò)Apollo客戶端從配置中心拉取配置信息

管理員通過(guò)Apollo配置中心修改或發(fā)布配置后君躺,會(huì)有兩種機(jī)制來(lái)保證應(yīng)用程序獲取最新配置:

1)Apollo配置中心主動(dòng)向客戶端推送最新的配置峭判;

2)Apollo客戶端會(huì)定時(shí)從Apollo配置中心拉取最新的配置。

通過(guò)以上推棕叫、拉的兩種機(jī)制共同來(lái)保證應(yīng)用程序能及時(shí)獲取到配置林螃。

Apollo的安裝部署

下載地址:https://github.com/ctripcorp/apollo/releases

image

兩種下載方式,一是直接下載上圖的畫框的三個(gè)分別是adminservice俺泣、configservice疗认、portal完残;二是下載source code源碼自己打包,zip 和 tar.gz 都可以横漏。這里使用的第二種方式谨设。

解釋一下為啥第一種下載方式會(huì)有三個(gè)包,這其實(shí)和Apollo的架構(gòu)有關(guān)绊茧。portal 是一個(gè)可視化界面會(huì)調(diào)用 adminservice 進(jìn)行配置管理和發(fā)布铝宵,可以認(rèn)為是 adminservice 的 client 端打掘;configservice 和 Apollo 的 client 保持長(zhǎng)連接华畏,configservice 服務(wù)于 Apollo client 進(jìn)行配置獲取,configservice 和 client 通過(guò)一種推拉結(jié)合的方式尊蚁,實(shí)現(xiàn)配置實(shí)時(shí)更新的同時(shí)亡笑,保證配置更新不丟失。所以不管是第一種方式還是第二種方式横朋,我們都需要運(yùn)行三個(gè)jar程序仑乌。

采用第二種方式,下載好源碼并解壓后倒導(dǎo)入idea琴锭,如下

image
image.gif

然后找到scripts文件夾并打開晰甚,有一個(gè) sql 文件夾,里面有兩個(gè) SQL 文件

image
image.gif

?

在mysql里執(zhí)行這兩個(gè)SQL 文件决帖,成功后會(huì)創(chuàng)建兩個(gè)數(shù)據(jù)庫(kù)

image
image.gif

?

然后注意到 scripts 目錄下有兩個(gè)文件厕九,build.bat 和 build.sh 文件,分別是Windows 和 linux用的地回。

需要打開對(duì)應(yīng)的文件更改一些參數(shù)扁远,如數(shù)據(jù)庫(kù)配置參數(shù)URL,用戶名密碼刻像,改成你自己的畅买。

下面這些是Erueka的不同環(huán)境的地址,我們就本地dev的不用改了

set dev_meta="http://localhost:8080"
set fat_meta="http://someIp:8080"
set uat_meta="http://anotherIp:8080"
set pro_meta="http://yetAnotherIp:8080"
image.gif

然后细睡,運(yùn)行就直接就是用maven打包了谷羞,打完之后在各自的target目錄下即可看到

image
image.gif

?

image
image.gif

?

image
image.gif

?

我是把這三個(gè)jar復(fù)制出來(lái),放到一個(gè)專門的目錄溜徙,方便運(yùn)行洒宝。

然后,依次啟動(dòng)三個(gè)jar

java -jar apollo-configservice-1.6.1.jar
java -jar apollo-adminservice-1.6.1.jar
java -jar apollo-portal-1.6.1.jar
image.gif

都啟動(dòng)后萌京,訪問(wèn)http://localhost:8070/ 進(jìn)入Apollo的配置管理中心雁歌,可以創(chuàng)建項(xiàng)目(walking是我自己創(chuàng)建的),稍后再講

image

然后訪問(wèn) http://localhost:8080/ 出現(xiàn)如下畫面知残,Apollo安裝部署成功靠瞎。

image

創(chuàng)建項(xiàng)目

點(diǎn)擊創(chuàng)建項(xiàng)目比庄,選擇部門,Apollo默認(rèn)的有兩個(gè)樣例乏盐,當(dāng)然你可以在右上角管理員工具里添加佳窑,稍后再說(shuō)。

然后填寫AppId父能,這是全局唯一的神凑,客戶端調(diào)用的時(shí)候要用這個(gè)。應(yīng)用名稱就隨意寫了何吝。

應(yīng)用負(fù)責(zé)人溉委,默認(rèn)的是Apollo,也可以在右上角管理員工具里增加爱榕。

項(xiàng)目管理員瓣喊,可以額外添加該項(xiàng)目的管理員

image

然后提交就行了。

然后就會(huì)進(jìn)入到該項(xiàng)目黔酥,默認(rèn)會(huì)有一個(gè)application 的命名空間

image

可以添加命名空間

image

我們可以點(diǎn)擊新增配置來(lái)添加參數(shù)

image

新添加的參數(shù)是未發(fā)布狀態(tài)藻三,可點(diǎn)擊發(fā)布按鈕使其生效

image
image
image

然后就發(fā)布成功了。

Apollo工作原理

下圖是Apollo架構(gòu)模塊的概覽

apollo架構(gòu)圖 by walking

各模塊職責(zé)

上圖簡(jiǎn)要描述了Apollo的總體設(shè)計(jì)跪者,我們可以從下往上看:

  • Config Service提供配置的讀取棵帽、推送等功能,服務(wù)對(duì)象是Apollo客戶端

  • Admin Service提供配置的修改渣玲、發(fā)布等功能逗概,服務(wù)對(duì)象是Apollo Portal(管理界面)

  • Eureka提供服務(wù)注冊(cè)和發(fā)現(xiàn),為了簡(jiǎn)單起見柜蜈,目前Eureka在部署時(shí)和Config Service是在一個(gè)JVM進(jìn)程中的

  • Config Service和Admin Service都是多實(shí)例仗谆、無(wú)狀態(tài)部署,所以需要將自己注冊(cè)到Eureka中并保持心跳

  • 在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)程中

分步執(zhí)行流程

  1. Apollo啟動(dòng)后,Config/Admin Service會(huì)自動(dòng)注冊(cè)到Eureka服務(wù)注冊(cè)中心至壤,并定期發(fā)送蓖迹活心跳。

  2. Apollo Client和Portal管理端通過(guò)配置的Meta Server的域名地址經(jīng)由Software Load Balancer(軟件負(fù)載均衡器)進(jìn)行負(fù)載均衡后分配到某一個(gè)Meta Server

  3. Meta Server從Eureka獲取Config Service和Admin Service的服務(wù)信息像街,相當(dāng)于是一個(gè)Eureka Client

  4. Meta Server獲取Config Service和Admin Service(IP+Port)失敗后會(huì)進(jìn)行重試

  5. 獲取到正確的Config Service和Admin Service的服務(wù)信息后黎棠,Apollo Client通過(guò)Config Service為應(yīng)用提供配置獲取晋渺、實(shí)時(shí)更新等功能;Apollo Portal管理端通過(guò)Admin Service提供配置新增、修改、發(fā)布等功能

核心概念

application (應(yīng)用)

這個(gè)很好理解漱竖,就是實(shí)際使用配置的應(yīng)用,Apollo客戶端在運(yùn)行時(shí)需要知道當(dāng)前應(yīng)用是誰(shuí)八千,從而可以去獲取對(duì)應(yīng)的配置

關(guān)鍵字:appId

environment (環(huán)境)

配置對(duì)應(yīng)的環(huán)境,Apollo客戶端在運(yùn)行時(shí)需要知道當(dāng)前應(yīng)用處于哪個(gè)環(huán)境燎猛,從而可以去獲取應(yīng)用的配置

關(guān)鍵字:env

cluster (集群)

一個(gè)應(yīng)用下不同實(shí)例的分組恋捆,比如典型的可以按照數(shù)據(jù)中心分,把上海機(jī)房的應(yīng)用實(shí)例分為一個(gè)集群扛门,把北京機(jī)房的應(yīng)用實(shí)例分為另一個(gè)集群鸠信。

關(guān)鍵字:cluster

namespace (命名空間)

一個(gè)應(yīng)用下不同配置的分組纵寝,可以簡(jiǎn)單地把namespace類比為文件论寨,不同類型的配置存放在不同的文件中,如數(shù)據(jù)庫(kù)配置文件爽茴,RPC配置文件葬凳,應(yīng)用自身的配置文件等

關(guān)鍵字:namespaces

它們的關(guān)系如下圖所示:

image

?

Spring Boot整合Apollo

Apollo搭建好之后,我們通過(guò)一個(gè)簡(jiǎn)單的SpringBoot項(xiàng)目來(lái)去從它上面獲取配置室奏,進(jìn)行一個(gè)測(cè)試火焰。

入門案例

1、添加Apollo client依賴

<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-client</artifactId>
    <version>${apollo.client.version}</version>
</dependency>
image.gif

2胧沫、application.yml添加配置

server:
  port: 8761
app:
  id: walking #AppId是應(yīng)用的身份信息昌简,是配置中心獲取配置的一個(gè)重要信息
apollo:
  meta: http://localhost:8080 #eureka地址
  bootstrap:
    enabled: true #在應(yīng)用啟動(dòng)階段,向Spring容器注入被托管的application.properties文件的配置信息

3绒怨、啟動(dòng)類上增加 @EnableApolloConfig 注解

@RestController
public class ApolloController {
    @Value("${test_key}")
    String testApollo;
    @GetMapping("testApollo")
    public Map<String,Object> testApollo() {
        Map<String,Object> result = new HashMap<>();
        result.put("testApollo",testApollo);
        return result;
    }
}

4纯赎、訪問(wèn)接口,拿到了配置value值

image

?

訪問(wèn)多個(gè)命名空間

1南蹂、修改application.yml犬金,增加 namespaces 選項(xiàng),填寫命名空間名稱六剥,application可以不用寫晚顷。

server:
  port: 8761
app:
  id: walking #AppId是應(yīng)用的身份信息,是配置中心獲取配置的一個(gè)重要信息
apollo:
  meta: http://localhost:8080 #eureka地址
  bootstrap:
    enabled: true #在應(yīng)用啟動(dòng)階段疗疟,向Spring容器注入被托管的application.properties文件的配置信息
    namespaces: TEST1.datasource-mysql.config

2该默、獲取另外一個(gè)命名空間內(nèi)的參數(shù) mysql.url

@RestController
public class ApolloController {
    @Value("${test_key}")
    String testApollo;
    @Value("${mysql.url}")
    String mysqlUrl;
    @GetMapping("testApollo")
    public Map<String,Object> testApollo() {
        Map<String,Object> result = new HashMap<String,Object>();
        result.put("testApollo",testApollo);
        result.put("mysqlUrl",mysqlUrl);
        return result;
    }
}

3、測(cè)試策彤,拿到了

image

動(dòng)態(tài)修改日志級(jí)別

日志模塊是每個(gè)項(xiàng)目中必須的栓袖,用來(lái)記錄程序運(yùn)行中的相關(guān)信息顿膨。一般在開發(fā)環(huán)境下使用DEBUG級(jí)別的日志輸出,為了方便查看問(wèn)題叽赊,而在線上一般都使用INFO或者ERROR級(jí)別的日志恋沃,主要記錄業(yè)務(wù)操作或者錯(cuò)誤的日志。

那么問(wèn)題來(lái)了必指,當(dāng)線上環(huán)境出現(xiàn)問(wèn)題希望輸出DEBUG日志信息輔助排查的時(shí)候怎么辦呢囊咏?以前確實(shí)是這么做的:修改配置文件,重新打包然后上傳重啟線上環(huán)境塔橡。很麻煩梅割,也很慢。

所以我們想通過(guò)把日志級(jí)別參數(shù)部署到 Apollo 上葛家,然后監(jiān)聽參數(shù)變化后從 Apollo 上獲取日志級(jí)別户辞,再修改日志級(jí)別,來(lái)達(dá)到熱更新的效果癞谒。

1底燎、引入日志包,這里使用的是lombok弹砚,比較方便演示

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
    <scope>provided</scope>
</dependency>

2双仍、application.yml???????

server:
  port: 8761
app:
  id: walking #AppId是應(yīng)用的身份信息,是配置中心獲取配置的一個(gè)重要信息
apollo:
  meta: http://localhost:8080
  bootstrap:
    enabled: true #在應(yīng)用啟動(dòng)階段桌吃,向Spring容器注入被托管的application.properties文件的配置信息朱沃。
    namespaces: TEST1.datasource-mysql.config
   eagerLoad:
      enabled: true #將Apollo配置的加載提到初始化日志系統(tǒng)之前
logging:
  level:
    com:
      walking:
        controller: info #根據(jù)包名調(diào)整controller包的日志級(jí)別,為了后面演示在配置中心動(dòng)態(tài)配置日志級(jí)別

3茅诱、增加了如下配置逗物,用于將 Apollo 配置的加載提到初始化日志系統(tǒng)之前,以及配置com.walking.controller包的日志級(jí)別為 debug

   eagerLoad:
      enabled: true #將Apollo配置的加載提到初始化日志系統(tǒng)之前
logging:
  level:
    com:
      walking:
        controller: debug #根據(jù)包名調(diào)整controller包的日志級(jí)別瑟俭,為了后面演示在配置中心動(dòng)態(tài)配置日志級(jí)別      

4翎卓、然后增加這樣一個(gè)參數(shù)用于部署日志級(jí)別

image

5、然后通過(guò)@ApolloConfigChangeListener注解監(jiān)聽配置的變化尔当,監(jiān)聽到配置變化時(shí)重新設(shè)置該目錄的日志級(jí)別???????

@Slf4j
@Configuration
public class LoggerConfig {
    private static final String LOGGER_TAG = "logging.level.";
    @Autowired
    private LoggingSystem loggingSystem;
    /*
     * 將Apollo服務(wù)端的中的配置注入這個(gè)類中莲祸。
     */
    @ApolloConfig
    private Config config;
    /*
     * @ApolloConfigChangeListener
     * value 指定監(jiān)聽哪個(gè) namespace,默認(rèn)是 application
     * interestedKeys 指定監(jiān)聽哪些key 如interestedKeys={"abc","123"},
     * interestedKeyPrefixes 指定監(jiān)聽的key(模糊匹配)
     * 監(jiān)聽配置中心配置的更新事件椭迎,若該事件發(fā)生锐帜,則調(diào)用refreshLoggingLevels方法,處理該事件畜号。
     * ConfigChangeEvent參數(shù):可以獲取被修改配置項(xiàng)的key集合缴阎,以及被修改配置項(xiàng)的新值、舊值和修改類型等信息简软。
     */
    @ApolloConfigChangeListener(value="application",interestedKeyPrefixes = {LOGGER_TAG})
    private void configChangeListter(ConfigChangeEvent changeEvent) {
        refreshLoggingLevels(changeEvent);
    }
    private void refreshLoggingLevels(ConfigChangeEvent changeEvent) {
        log.info("apollo config changed,LoggerConfig 更新日志級(jí)別");
        Set<String> keyNames = changeEvent.changedKeys();
        for (String key : keyNames) {
            if (StringUtils.containsIgnoreCase(key, LOGGER_TAG)) {
                ConfigChange change = changeEvent.getChange(key);
                String newLevel = change.getNewValue();
                String oldLevel = change.getOldValue();
                LogLevel level = LogLevel.valueOf(newLevel.toUpperCase());
                String packageName = key.replace(LOGGER_TAG, "");
                loggingSystem.setLogLevel(packageName, level);
                log.info("package logLevel changed==>key:{},package:{},oldLevel:{},newLevel:{},changeType:{}",
                        key, packageName, oldLevel,newLevel,change.getChangeType());
            }
        }
        log.info("apollo config changed,LoggerConfig 更新完畢");
    }
}

6蛮拔、我們?cè)?controller 的接口里增加如下代碼述暂,便于觀察日志級(jí)別是否改變
?????

log.debug("debug...");
log.info("info...");
log.error("error...");
log.warn("warn...");

7、首先啟動(dòng)spring boot項(xiàng)目建炫,我們?cè)L問(wèn)測(cè)試接口畦韭,查看日志。

image

正是我們?cè)?application.yml 上設(shè)置的 debug 日志級(jí)別肛跌。

8艺配、接下來(lái)我們?cè)?Apollo 上修改日志級(jí)別為 warn,然后發(fā)布衍慎。

日志里已經(jīng)看到我們的應(yīng)用已經(jīng)監(jiān)聽到配置的變化转唉,并更新了日志級(jí)別

image

9、訪問(wèn)一下測(cè)試接口稳捆,可看到已經(jīng)生效了赠法。

image

?
這就實(shí)現(xiàn)了日志級(jí)別的熱修改。

如我們可以完全依賴 Apollo 上的日志級(jí)別乔夯,就可以直接把 application.yml 的日志級(jí)別去掉了砖织。

但是,我們需要修改一下我們的 LoggerConfig 類了驯嘱,因?yàn)槟壳斑@個(gè)類的修改日志級(jí)別的功能是在監(jiān)聽到 Apollo 的配置變化了之后修改的镶苞,當(dāng)我們的應(yīng)用剛部署時(shí)是沒(méi)有修改配置的喳坠,所以就沒(méi)有觸發(fā)執(zhí)行這個(gè)設(shè)置日志級(jí)別的方法鞠评。

我們只需要增加一個(gè)init方法即可,并在其上添加@PostConstruct 注解即可壕鹉,這個(gè)注解就是初始化時(shí)就調(diào)用該方法剃幌,和 init method 作用一樣,這樣在我們的系統(tǒng)啟動(dòng)時(shí)就可以從 Apollo 上拿到配置參數(shù)從而設(shè)置日志級(jí)別晾浴。

@PostConstruct //加載這個(gè)類時(shí)就執(zhí)行
private void init(){
    log.info("初始化日志級(jí)別...");
    Set<String> keyNames = config.getPropertyNames();
    for (String key : keyNames) {
        if (StringUtils.containsIgnoreCase(key, LOGGER_TAG)) {
            String strLevel = config.getProperty(key, "info");
            LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
            String packageName = key.replace(LOGGER_TAG, "");
            loggingSystem.setLogLevel(packageName, level);
            log.info("init package logLevel==>key:{},package:{},level:{}", key, packageName, strLevel);
        }
    }
    log.info("初始化日志級(jí)別完畢");
}

啟動(dòng)

image

測(cè)試一下是不是warn級(jí)別

訪問(wèn)測(cè)試接口负乡,可以看到正是 warn級(jí)別。

image

?
再去修改為info脊凰,客戶端應(yīng)用監(jiān)聽到修改并重新設(shè)置了日志級(jí)別

image

訪問(wèn)測(cè)試接口抖棘,已修改為info級(jí)別。

image

Apollo還支持狸涌,灰度發(fā)布切省、分環(huán)境、分集群配置帕胆,篇幅的原因關(guān)于Apollo應(yīng)用的介紹今天就先到這里啦朝捆。

覺(jué)得有幫助的話請(qǐng)點(diǎn)贊吧?~

熱文:

Redis的各種數(shù)據(jù)類型到底能玩出什么花兒?

Redis分布式鎖實(shí)戰(zhàn)

什么是消息隊(duì)列袄帘芙盘?

聯(lián)合索引在B+樹上的存儲(chǔ)結(jié)構(gòu)及數(shù)據(jù)查找方式

嘮叨~

歡迎關(guān)注公眾號(hào)驯用,編程大道,之前整理的 redis 和 MQ 的知識(shí)點(diǎn)思維導(dǎo)圖分享給大家

?
image
image

?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末儒老,一起剝皮案震驚了整個(gè)濱河市蝴乔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驮樊,老刑警劉巖淘这,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異巩剖,居然都是意外死亡铝穷,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門佳魔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)曙聂,“玉大人,你說(shuō)我怎么就攤上這事鞠鲜∧梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵贤姆,是天一觀的道長(zhǎng)榆苞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)霞捡,這世上最難降的妖魔是什么坐漏? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮碧信,結(jié)果婚禮上赊琳,老公的妹妹穿的比我還像新娘。我一直安慰自己砰碴,他們只是感情好躏筏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著呈枉,像睡著了一般趁尼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猖辫,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天酥泞,我揣著相機(jī)與錄音,去河邊找鬼住册。 笑死婶博,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凡人,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼名党,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了挠轴?” 一聲冷哼從身側(cè)響起传睹,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎岸晦,沒(méi)想到半個(gè)月后欧啤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡启上,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年邢隧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冈在。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倒慧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出包券,到底是詐尸還是另有隱情纫谅,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布溅固,位于F島的核電站付秕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏侍郭。R本人自食惡果不足惜询吴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望励幼。 院中可真熱鬧汰寓,春花似錦、人聲如沸苹粟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嵌削。三九已至,卻和暖如春望艺,著一層夾襖步出監(jiān)牢的瞬間苛秕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工找默, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留艇劫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓惩激,卻偏偏與公主長(zhǎng)得像店煞,于是被迫代替她去往敵國(guó)和親蟹演。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355