1. 程式人生 > >結合實際場景談一談微服務配置

結合實際場景談一談微服務配置

作為 Nacos 5W1H 的系列文章,本文將圍繞“Where”,講述 Nacos 配置管理的三個典型的應用場景:

資料庫連線資訊
限流閾值和降級開關
流量的動態排程
上一篇:Nacos幫我解決了什麼問題?

資料庫連線資訊
曾經有朋友跟我聊過一個問題,“業務飛速發展,團隊越來越大,人員流動也相對頻繁起來,怎麼才能更好的保證資料的安全性,不被洩露呢?”。他提到這樣一個場景,公司創立初期,服務後端的程式碼都是他一行一行碼出來的,當時只有他一個人,後端與資料庫的連線配置資訊也就直接放置在專案的配置檔案中。他使用的是 Spring Boot 框架,配置資訊就是存放在 application.properties 中,使用 Spring 的 profile 屬性保證不同環境連線不同的資料庫。如下所示:

生產環境:application-prod.properties

spring.datasource.url=生產環境的資料庫連線地址
spring.datasource.username=生產環境的資料庫使用者賬號
spring.datasource.password=生產環境的資料庫使用者密碼
開發環境:application-dev.properties

spring.datasource.url=開發環境的資料庫連線地址
spring.datasource.username=開發環境的資料庫使用者賬號
spring.datasource.password=開發環境的資料庫使用者密碼
測試、預發環境也是類似。這種將資料庫連線資訊直接放置在配置檔案中,跟著專案程式碼一起通過 Git 管理,的確是有蠻大的資料洩露的風險。試想,一個新來不久的小夥伴,他一當要投入研發工作,有 Git Pull 程式碼的許可權之後,代表他可能就擁有了直接操作線上資料庫的許可權了。當時的我給他建議可以通過以下幾個方面去降低資料風險:

將資料庫連線資訊等敏感配置從專案中剝離;
資料庫增加 IP 白名單連線限制;
最小許可權原則:每個賬號只配置所必需的許可權,避免刪表刪庫等高危操作;
定期修改資料庫賬號、密碼。
回想起來,我當時給的建議並沒有完全解決他的問題,甚至還帶來了其他一些問題。例如,上述的第一點,“將敏感配置從專案剝離”,剝離出來的敏感配置存放到哪裡?怎麼管理這些配置呢?也許,你會想到,存放到應用部署機器的環境變數或某個檔案中。不,一樣有風險,說不定哪天開發同學必須得登入上機器排查問題,就有洩露的風險,總之,得儘可能地做到在整個開發流程都不會有任何洩露的風險。應用中可能不只是連線一個數據源,分庫分表的情況,不同資料儲存(如 MySQL / Redis / Elasticsearch 等)的情況,還有,其他更多敏感配置項,配置資料的增多會給管理帶來不便。

另外,“定期修改資料庫賬號、密碼”,修改後我能怎麼方便快捷的下發到所有應用程式中呢?既然是敏感配置,其變更也會帶來不少的風險,我需要能先到小量的幾臺機器驗證,保證對業務無影響,我再全部下發到其他所有的機器上去,是否還得有“灰度釋出”的功能呢?賬號密碼修改下發後,應用出現異常,影響到業務了,我要怎麼快速地回滾呢?是否還得有“版本控制”、“快速回滾”的功能呢?不是所有的開發同學都有許可權能修改敏感配置資訊,是否還需要有“許可權管控”的功能?對敏感配置的任何操作都應該被記錄,是否還需要有“變更審計”的功能呢?

現在,我有了更好的建議:使用 Nacos 配置管理模組,將敏感配置資訊都存放到 Nacos 中。Nacos 配置管理,其中一個立身之本就是為敏感配置保駕護航。它提供上述場景所需的功能,通過名稱空間區分不同環境(開發、測試、預發、生產),通過“版本控制”保證變更可追溯,通過“快速回滾”保證錯誤變更時影響最小,通過的“灰度釋出”功能保障配置安全平穩地變更,還有更多更全面功能(許可權管控、變更審計等)即將支援。

那麼,怎麼將敏感配置專案的配置檔案中遷移到 Nacos 中呢?下面以 Spring Boot 連線 MySQL 為例:

新增依賴

<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>${latest.version}</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
這裡是簡單的示例,在實際生產中,還需配置 Nacos 名稱空間資訊(區分環境)、鑑權資訊(如 AccessKey、SecretKey 等,即將支援的許可權訪問控制)。而 Nacos 配置模組對應的阿里雲產品 ACM,藉助於 ECS 例項 RAM 角色,最終能到達連 AccessKey、SecretKey 都不需要填寫的目的。

新增 @NacosPropertySource 註解

@SpringBootApplication
@NacosPropertySource(dataId = "mysql.properties")
public class SpringBootMySQLApplication {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
在本地啟動的 Nacos 控制檯上新增 dataId 為 mysql.properties 的配置,配置內容為 MySQL 連線配置資訊:

通過這四個簡單的步驟,就將 MySQL 連線資訊從原來的 application.properties 遷移到 Nacos 的,讓 Nacos 將敏感配置管控起來,大大降低資料洩露的風險。同時,Nacos 配置管理提供的“統一管控”、“版本控制”、“快速回滾”等強大的功能也為其運維管理帶來極大的便利。

完整示例程式碼請參看:https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-boot-example/nacos-spring-boot-config-mysql-example

限流閾值和降級開關
限流、降級,眾所周知,是在開發高併發系統過程中需要考慮的兩大關鍵點,是執行時保護系統的兩大利器。限流閾值和降級開關,最終是抽象為一個個的配置項,要想實現執行時的動態調整閾值和開關的啟停,將這些配置項存放到 Nacos 的配置模組中最適合不過了。

在今年 8 月的時候,阿里巴巴開源了 Sentinel,以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。在阿里巴巴內部,Nacos 跟 Sentinel 就是多年攜手相伴,砥礪前行的好機油,為雙 11 等各種大促立下了功勞,也為剁手黨提供了良好的購物體驗。

下面就以 Sentinel 流控為例,演示如果通過 Nacos 來做到執行時的動態控制流量:

新增依賴
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>${latest.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
<version>${latest.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>${latest.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${latest.version}</version>
2.模擬併發請求

final class RunTask implements Runnable {br/>@Override
public 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 等,並將其設定為 Sentinel 的資料來源

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<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId,
    source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
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.在本地啟動的 Nacos 控制檯中新建 dataId 為 com.alibaba.nacos.demo.flow.rule 的流控配置

結合實際場景談一談微服務配置

5.執行 NacosDynamicFlowDemo,你會看到如下標準輸出資訊

結合實際場景談一談微服務配置

再到 Nacos 控制檯修改剛剛新建的流控配置,將限流閾值 count 的值修改為 1.0,完整的標準輸出資訊如下

結合實際場景談一談微服務配置

以上示例演示瞭如何通過 Nacos + Sentinel 實現動態流量控制的能力,核心就是用到了 Nacos 配置模組“動態推送”的能力。原理是 sentinel-datasource-nacos 集成了 nacos-client ,其與 nacos-server 維持著連線,當用戶在 Nacos 控制檯進行配置變更時,nacos-server 會快速地將該配置的最新內容推送到 nacos-client 中,Sentinel 一拿到最新的流控配置,就轉換了流控策略,如示例將流控閾值調整為 1.0,限制為更少的流量進入系統的業務處理流程。

完整示例程式碼請參看:https://github.com/nacos-group/nacos-examples/tree/master/nacos-sentinel-example

流量的動態排程

業務發展壯大到一定的規模,單一的叢集已經承載不了全部的使用者請求,需要將使用者的流量分流到不同的叢集上。當然,更進一步的方案是:不同的叢集位於不同的區域,這樣,除了緩解業務處理的壓力,也給系統帶來容災的能力。

比如,某電商系統有 1 億使用者量,將系統的流量按照使用者的 ID 進行切分,ID 為 1-1000W 的使用者請求分發到區域 A 的叢集 a 上,ID 為 10001W-2000W 的使用者請求流量分發到區域 B 的叢集 b 上,以此類推,最終將所有使用者的請求流量打散到 10 個不同區域的叢集上,同時,每個叢集冗餘了一些系統資源。當區域 A 的機房發生不可抗的災難(如地震)時,我們需要有動態排程流量的能力,最好能秒級得將流量從區域 A 排程到另外可用的區域的叢集上。

這正是 Nacos 配置管理大有作為的地方,將使用者 ID 的分片和對應的路由規則存放在 Nacos 的中,配合統一接入層等的元件,就能將流量打散到各個叢集上,進而讓系統能承載更大的流量,以更好的支撐業務的發展。另外,將其存放與 Nacos 中,也就具備了配置“動態化”的能力,一旦某區域出現基礎設施無法及時恢復的問題時,只需在 Nacos 的控制檯上修改 ID 分片的路由規則,就能將有問題的區域流量快速切換到其他可用的區域上,保障對業務幾乎無損。Nacos 在阿里內部能做到秒級推送到十萬級別機器上的推送效率。

總結
除了以上三個場景,其實還有更多更大膽的應用場景,如“大資料實時計算演算法調整”、“異地容災多活”、“應用業務場景動態推送”等等,可以參看 Nacos 的阿里雲產品 ACM 的使用場景 。Nacos 配置管理模組,將敏感配置收攏管控起來,極大降低資料洩露等風險,並且提供如“動態推送”、“版本控制”、“快速回滾”等功能,保障了敏感配置的變更安全平穩的執行。

在限流與降級的場景,通過一個示例,為大家演示瞭如何通過 Nacos + Sentinel 實現流量的動態控制,這也是 Nacos 配置管理的一個十分典型的應用場景。降級也一樣,大促高峰期間將某個非關鍵的系統元件進行關閉,在過了高峰期後再開啟,這個也是可以通過 Nacos 的“動態推送”的功能來實現。

總之,只要系統涉及到了“敏感的配置”、“動態的配置”,都應該考慮將配置放入到 Nacos 中,讓 Nacos 管控起來。