作為 Nacos 5W1H 的系列文章,本文將圍繞“Where”,講述 Nacos 配置管理的三個(gè)典型的應(yīng)用場景:
數(shù)據(jù)庫連接信息
限流閾值和降級開關(guān)
流量的動(dòng)態(tài)調(diào)度
數(shù)據(jù)庫連接信息
曾經(jīng)有朋友跟我聊過一個(gè)問題,“業(yè)務(wù)飛速發(fā)展,團(tuán)隊(duì)越來越大,人員流動(dòng)也相對頻繁起來,怎么才能更好的保證數(shù)據(jù)的安全性,不被泄露呢?”。他提到這樣一個(gè)場景,公司創(chuàng)立初期,服務(wù)后端的代碼都是他一行一行碼出來的,當(dāng)時(shí)只有他一個(gè)人,后端與數(shù)據(jù)庫的連接配置信息也就直接放置在項(xiàng)目的配置文件中。他使用的是 Spring Boot 框架,配置信息就是存放在 application.properties 中,使用 Spring 的 profile 屬性保證不同環(huán)境連接不同的數(shù)據(jù)庫。如下所示:
生產(chǎn)環(huán)境:application-prod.properties
spring.datasource.url=生產(chǎn)環(huán)境的數(shù)據(jù)庫連接地址 spring.datasource.username=生產(chǎn)環(huán)境的數(shù)據(jù)庫用戶賬號 spring.datasource.password=生產(chǎn)環(huán)境的數(shù)據(jù)庫用戶密碼
開發(fā)環(huán)境:application-dev.properties
spring.datasource.url=開發(fā)環(huán)境的數(shù)據(jù)庫連接地址 spring.datasource.username=開發(fā)環(huán)境的數(shù)據(jù)庫用戶賬號 spring.datasource.password=開發(fā)環(huán)境的數(shù)據(jù)庫用戶密碼
測試、預(yù)發(fā)環(huán)境也是類似。這種將數(shù)據(jù)庫連接信息直接放置在配置文件中,跟著項(xiàng)目代碼一起通過 Git 管理,的確是有蠻大的數(shù)據(jù)泄露的風(fēng)險(xiǎn)。試想,一個(gè)新來不久的小伙伴,他一當(dāng)要投入研發(fā)工作,有 Git Pull 代碼的權(quán)限之后,代表他可能就擁有了直接操作線上數(shù)據(jù)庫的權(quán)限了。當(dāng)時(shí)的我給他建議可以通過以下幾個(gè)方面去降低數(shù)據(jù)風(fēng)險(xiǎn):
將數(shù)據(jù)庫連接信息等敏感配置從項(xiàng)目中剝離;
數(shù)據(jù)庫增加 IP 白名單連接限制;
最小權(quán)限原則:每個(gè)賬號只配置所必需的權(quán)限,避免刪表刪庫等高危操作;
定期修改數(shù)據(jù)庫賬號、密碼。
回想起來,我當(dāng)時(shí)給的建議并沒有完全解決他的問題,甚至還帶來了其他一些問題。例如,上述的第一點(diǎn),“將敏感配置從項(xiàng)目剝離”,剝離出來的敏感配置存放到哪里?怎么管理這些配置呢?也許,你會(huì)想到,存放到應(yīng)用部署機(jī)器的環(huán)境變量或某個(gè)文件中。不,一樣有風(fēng)險(xiǎn),說不定哪天開發(fā)同學(xué)必須得登錄上機(jī)器排查問題,就有泄露的風(fēng)險(xiǎn),總之,得盡可能地做到在整個(gè)開發(fā)流程都不會(huì)有任何泄露的風(fēng)險(xiǎn)。應(yīng)用中可能不只是連接一個(gè)數(shù)據(jù)源,分庫分表的情況,不同數(shù)據(jù)存儲(chǔ)(如 MySQL / Redis / Elasticsearch 等)的情況,還有,其他更多敏感配置項(xiàng),配置數(shù)據(jù)的增多會(huì)給管理帶來不便。
另外,“定期修改數(shù)據(jù)庫賬號、密碼”,修改后我能怎么方便快捷的下發(fā)到所有應(yīng)用程序中呢?既然是敏感配置,其變更也會(huì)帶來不少的風(fēng)險(xiǎn),我需要能先到小量的幾臺(tái)機(jī)器驗(yàn)證,保證對業(yè)務(wù)無影響,我再全部下發(fā)到其他所有的機(jī)器上去,是否還得有“灰度發(fā)布”的功能呢?賬號密碼修改下發(fā)后,應(yīng)用出現(xiàn)異常,影響到業(yè)務(wù)了,我要怎么快速地回滾呢?是否還得有“版本控制”、“快速回滾”的功能呢?不是所有的開發(fā)同學(xué)都有權(quán)限能修改敏感配置信息,是否還需要有“權(quán)限管控”的功能?對敏感配置的任何操作都應(yīng)該被記錄,是否還需要有“變更審計(jì)”的功能呢?
現(xiàn)在,我有了更好的建議:使用 Nacos 配置管理模塊,將敏感配置信息都存放到 Nacos 中。Nacos 配置管理,其中一個(gè)立身之本就是為敏感配置保駕護(hù)航。它提供上述場景所需的功能,通過命名空間區(qū)分不同環(huán)境(開發(fā)、測試、預(yù)發(fā)、生產(chǎn)),通過“版本控制”保證變更可追溯,通過“快速回滾”保證錯(cuò)誤變更時(shí)影響最小,通過的“灰度發(fā)布”功能保障配置安全平穩(wěn)地變更,還有更多更全面功能(權(quán)限管控、變更審計(jì)等)即將支持。
那么,怎么將敏感配置項(xiàng)目的配置文件中遷移到 Nacos 中呢?下面以 Spring Boot 連接 MySQL 為例:
添加依賴
com.alibaba.boot nacos-config-spring-boot-starter ${latest.version}
注意 Spring Boot 1.x 使用 nacos-config-spring-boot-starter 0.1.x 版本,Spring Boot 2.x 使用 nacos-config-spring-boot-starter 0.2.x 版本。
在 application.properties 中添加 Nacos 連接配置
nacos.config.server-addr=127.0.0.1:8848
這里是簡單的示例,在實(shí)際生產(chǎn)中,還需配置 Nacos 命名空間信息(區(qū)分環(huán)境)、鑒權(quán)信息(如 AccessKey、SecretKey 等,即將支持的權(quán)限訪問控制)。而 Nacos 配置模塊對應(yīng)的阿里云產(chǎn)品 ACM,借助于 ECS 實(shí)例 RAM 角色,最終能到達(dá)連 AccessKey、SecretKey 都不需要填寫的目的。
添加 @NacosPropertySource 注解
@SpringBootApplication@NacosPropertySource(dataId?=?"mysql.properties")public?class?SpringBootMySQLApplication?{public?static?void?main(String[]?args)?{
????SpringApplication.run(Application.class,?args);
}在本地啟動(dòng)的 Nacos 控制臺(tái)上新增 dataId 為 mysql.properties 的配置,配置內(nèi)容為 MySQL 連接配置信息:
通過這四個(gè)簡單的步驟,就將 MySQL 連接信息從原來的 application.properties 遷移到 Nacos 的,讓 Nacos 將敏感配置管控起來,大大降低數(shù)據(jù)泄露的風(fēng)險(xiǎn)。同時(shí),Nacos 配置管理提供的“統(tǒng)一管控”、“版本控制”、“快速回滾”等強(qiáng)大的功能也為其運(yùn)維管理帶來極大的便利。
限流閾值和降級開關(guān)
限流、降級,眾所周知,是在開發(fā)高并發(fā)系統(tǒng)過程中需要考慮的兩大關(guān)鍵點(diǎn),是運(yùn)行時(shí)保護(hù)系統(tǒng)的兩大利器。限流閾值和降級開關(guān),最終是抽象為一個(gè)個(gè)的配置項(xiàng),要想實(shí)現(xiàn)運(yùn)行時(shí)的動(dòng)態(tài)調(diào)整閾值和開關(guān)的啟停,將這些配置項(xiàng)存放到 Nacos 的配置模塊中最適合不過了。
在今年 8 月的時(shí)候,阿里巴巴開源了 Sentinel,以流量為切入點(diǎn),從流量控制、熔斷降級、系統(tǒng)負(fù)載保護(hù)等多個(gè)維度保護(hù)服務(wù)的穩(wěn)定性。在阿里巴巴內(nèi)部,Nacos 跟 Sentinel 就是多年攜手相伴,砥礪前行的好機(jī)油,為雙 11 等各種大促立下了功勞,也為剁手黨提供了良好的購物體驗(yàn)。
下面就以 Sentinel 流控為例,演示如果通過 Nacos 來做到運(yùn)行時(shí)的動(dòng)態(tài)控制流量:
添加依賴
com.alibaba.csp sentinel-core ${latest.version} com.alibaba.csp sentinel-datasource-extension ${latest.version} com.alibaba.csp sentinel-datasource-nacos ${latest.version} com.alibaba fastjson ${latest.version}
2.模擬并發(fā)請求
final?class?RunTask?implements?Runnable?{@Overridepublic?void?run()?{????while?(!stop)?{
????????Entry?entry?=?null;????????try?{
????????????entry?=?SphU.entry(resourceName);????????????//?token?acquired,?means?pass
????????????pass.addAndGet(1);
????????}?catch?(BlockException?e1)?{
????????????block.incrementAndGet();
????????}?catch?(Exception?e2)?{????????????//?biz?exception
????????}?finally?{
????????????total.incrementAndGet();????????????if?(entry?!=?null)?{
????????????????entry.exit();
????????????}
????????}
????????Random?random2?=?new?Random();????????try?{
????????????TimeUnit.MILLISECONDS.sleep(random2.nextInt(50));
????????}?catch?(InterruptedException?e)?{????????????//?ignore
????????}
????}
}3.配置 Nacos 連接信息與 dataId 等,并將其設(shè)置為 Sentinel 的數(shù)據(jù)源
public?class?NacosDynamicFlowDemo?{private?static?final?String?KEY?=?"TestResource";public?static?void?main(String[]?args)?{????final?String?remoteAddress?=?"localhost";????final?String?groupId?=?"DEFAULT_GROUP";????final?String?dataId?=?"com.alibaba.nacos.demo.flow.rule";
????ReadableDataSource>?flowRuleDataSource?=?new?NacosDataSource<>(remoteAddress,?groupId,?dataId,
????????source?->?JSON.parseObject(source,?new?TypeReference>()?{}));
????FlowRuleManager.register2Property(flowRuleDataSource.getProperty());????
????//?Assume?we?config:?resource?is?`TestResource`,?initial?QPS?threshold?is?5.
????FlowQpsRunner?runner?=?new?FlowQpsRunner(KEY,?1,?10000);
????runner.simulateTraffic();
????runner.tick();
}
4.在本地啟動(dòng)的 Nacos 控制臺(tái)中新建 dataId 為 com.alibaba.nacos.demo.flow.rule 的流控配置
5.運(yùn)行 NacosDynamicFlowDemo,你會(huì)看到如下標(biāo)準(zhǔn)輸出信息
再到 Nacos 控制臺(tái)修改剛剛新建的流控配置,將限流閾值 count 的值修改為 1.0,完整的標(biāo)準(zhǔn)輸出信息如下
以上示例演示了如何通過 Nacos + Sentinel 實(shí)現(xiàn)動(dòng)態(tài)流量控制的能力,核心就是用到了 Nacos 配置模塊“動(dòng)態(tài)推送”的能力。原理是 sentinel-datasource-nacos 集成了 nacos-client ,其與 nacos-server 維持著連接,當(dāng)用戶在 Nacos 控制臺(tái)進(jìn)行配置變更時(shí),nacos-server 會(huì)快速地將該配置的最新內(nèi)容推送到 nacos-client 中,Sentinel 一拿到最新的流控配置,就轉(zhuǎn)換了流控策略,如示例將流控閾值調(diào)整為 1.0,限制為更少的流量進(jìn)入系統(tǒng)的業(yè)務(wù)處理流程。
完整示例代碼請參看:https://github.com/nacos-group/nacos-examples/tree/master/nacos-sentinel-example
流量的動(dòng)態(tài)調(diào)度
業(yè)務(wù)發(fā)展壯大到一定的規(guī)模,單一的集群已經(jīng)承載不了全部的用戶請求,需要將用戶的流量分流到不同的集群上。當(dāng)然,更進(jìn)一步的方案是:不同的集群位于不同的區(qū)域,這樣,除了緩解業(yè)務(wù)處理的壓力,也給系統(tǒng)帶來容災(zāi)的能力。
比如,某電商系統(tǒng)有 1 億用戶量,將系統(tǒng)的流量按照用戶的 ID 進(jìn)行切分,ID 為 1-1000W 的用戶請求分發(fā)到區(qū)域 A 的集群 a 上,ID 為 10001W-2000W 的用戶請求流量分發(fā)到區(qū)域 B 的集群 b 上,以此類推,最終將所有用戶的請求流量打散到 10 個(gè)不同區(qū)域的集群上,同時(shí),每個(gè)集群冗余了一些系統(tǒng)資源。當(dāng)區(qū)域 A 的機(jī)房發(fā)生不可抗的災(zāi)難(如地震)時(shí),我們需要有動(dòng)態(tài)調(diào)度流量的能力,最好能秒級得將流量從區(qū)域 A 調(diào)度到另外可用的區(qū)域的集群上。
這正是 Nacos 配置管理大有作為的地方,將用戶 ID 的分片和對應(yīng)的路由規(guī)則存放在 Nacos 的中,配合統(tǒng)一接入層等的組件,就能將流量打散到各個(gè)集群上,進(jìn)而讓系統(tǒng)能承載更大的流量,以更好的支撐業(yè)務(wù)的發(fā)展。另外,將其存放與 Nacos 中,也就具備了配置“動(dòng)態(tài)化”的能力,一旦某區(qū)域出現(xiàn)基礎(chǔ)設(shè)施無法及時(shí)恢復(fù)的問題時(shí),只需在 Nacos 的控制臺(tái)上修改 ID 分片的路由規(guī)則,就能將有問題的區(qū)域流量快速切換到其他可用的區(qū)域上,保障對業(yè)務(wù)幾乎無損。Nacos 在阿里內(nèi)部能做到秒級推送到十萬級別機(jī)器上的推送效率。
總結(jié)
除了以上三個(gè)場景,其實(shí)還有更多更大膽的應(yīng)用場景,如“大數(shù)據(jù)實(shí)時(shí)計(jì)算算法調(diào)整”、“異地容災(zāi)多活”、“應(yīng)用業(yè)務(wù)場景動(dòng)態(tài)推送”等等,可以參看 Nacos 的阿里云產(chǎn)品 ACM 的使用場景 。Nacos 配置管理模塊,將敏感配置收攏管控起來,極大降低數(shù)據(jù)泄露等風(fēng)險(xiǎn),并且提供如“動(dòng)態(tài)推送”、“版本控制”、“快速回滾”等功能,保障了敏感配置的變更安全平穩(wěn)的執(zhí)行。
在限流與降級的場景,通過一個(gè)示例,為大家演示了如何通過 Nacos + Sentinel 實(shí)現(xiàn)流量的動(dòng)態(tài)控制,這也是 Nacos 配置管理的一個(gè)十分典型的應(yīng)用場景。降級也一樣,大促高峰期間將某個(gè)非關(guān)鍵的系統(tǒng)組件進(jìn)行關(guān)閉,在過了高峰期后再開啟,這個(gè)也是可以通過 Nacos 的“動(dòng)態(tài)推送”的功能來實(shí)現(xiàn)。
總之,只要系統(tǒng)涉及到了“敏感的配置”、“動(dòng)態(tài)的配置”,都應(yīng)該考慮將配置放入到 Nacos 中,讓 Nacos 管控起來。
電子發(fā)燒友App







































評論