微服務(wù)確實(shí)是行業(yè)的一個(gè)趨勢,我自己也在把一些項(xiàng)目往微服務(wù)架構(gòu)遷移。玩微服務(wù)架構(gòu)配置中心是一個(gè)繞不過去的東西,有很多大牌的可以選,比如spring-cloud-config,apoll,disconf等等。而我為什么還要造一個(gè)輪子呢?一來這些都不是.net實(shí)現(xiàn)的,我就想試試用.net?core實(shí)現(xiàn)一個(gè),而且他們也對(duì).net不太友好,也只有apoll提供了官方的.net客戶端。二來這些組件都太重量級(jí)了,比如apoll,光跑起來就要部署多個(gè)節(jié)點(diǎn)(admin,portal,meta?sevice)還要依賴eureka。很多舊的項(xiàng)目往微服務(wù)遷移的時(shí)候并不是一下次全部調(diào)整完成的,可能是一步步來的,比如先把所有的服務(wù)都容器化,并沒有使用微服務(wù)全家桶。而且有的項(xiàng)目也不需要微服務(wù)全家桶,畢竟微服務(wù)不是銀彈,很多項(xiàng)目單體結(jié)構(gòu)就足夠了,有些項(xiàng)目傳統(tǒng)的SOA架構(gòu)也可以了。(嘮叨一句,那種毫無流量毫無并發(fā)的項(xiàng)目,幾人幾天就搞完的強(qiáng)上微服務(wù)真的好嗎?)但是這些項(xiàng)目也可能是分布式的,容器化部署的,那么這些項(xiàng)目我覺得也是需要配置中心的,因?yàn)樵诜植际?、容器化環(huán)境下更改配置實(shí)在是太麻煩了??梢哉f配置中心并不是微服務(wù)獨(dú)有的。基于以上原因我提煉了一些配置中心必備的功能,做的盡量簡單(陋),開發(fā)了AgileConfig,繼續(xù)為.net?core的生態(tài)盡一份綿薄之力。???
Github求star:[AgileConfig](https://github.com/kklldog/AgileConfig)
#?AgileConfig
這是一個(gè)基于.net?core開發(fā)的輕量級(jí)配置中心。
1.?部署簡單,最少只需要一個(gè)數(shù)據(jù)節(jié)點(diǎn),支持docker部署
2.?支持多節(jié)點(diǎn)分布式部署來保證高可用
3.?配置支持按應(yīng)用隔離,應(yīng)用內(nèi)配置支持分組隔離
4.?使用長連接技術(shù),配置信息實(shí)時(shí)推送至客戶端
5.?支持IConfiguration,IOptions模式讀取配置,原程序幾乎可以不用改造
6.?配置修改支持版本記錄,隨時(shí)回滾配置
7.?如果所有節(jié)點(diǎn)都故障,客戶端支持從本地緩存讀取配置
##?架構(gòu)

AgileConfig的架構(gòu)比較簡單,主要是分3塊:
###?客戶端
客戶端程序是使用netstandard2.0開發(fā)的一個(gè)類庫,方便.net?core程序接入,nuget搜a(bǔ)gileconfig.client就可以安裝。可以在啟動(dòng)客戶端的時(shí)候配置多個(gè)節(jié)點(diǎn)的地址,客戶端會(huì)隨機(jī)挑選一個(gè)進(jìn)行連接,連接成功后會(huì)維持一個(gè)websocket長連接。如果連接的節(jié)點(diǎn)發(fā)生故障導(dǎo)致連接中斷,客戶端會(huì)繼續(xù)隨機(jī)一個(gè)節(jié)點(diǎn)進(jìn)行連接,直到連接成功。
###?節(jié)點(diǎn)、管理程序
節(jié)點(diǎn)是使用asp.net?core開發(fā)的一個(gè)服務(wù)。為了部署簡單,直接把管理程序跟節(jié)點(diǎn)服務(wù)合二為一了。任何一個(gè)節(jié)點(diǎn)都可以在啟動(dòng)的時(shí)候配置環(huán)境變量開啟管理程序功能。
###?數(shù)據(jù)庫
使用數(shù)據(jù)庫來存儲(chǔ)數(shù)據(jù),目前支持Sqlserver,?Mysql,?Sqlite?三種數(shù)據(jù)庫。因?yàn)榉?wù)端使用EF?Core框架訪問數(shù)據(jù),原則上只要EF?Core支持的數(shù)據(jù)庫,節(jié)點(diǎn)就可以很方便的支持它。
##?部署服務(wù)端
##?初始化數(shù)據(jù)庫
用戶只需要手工建一個(gè)空庫,所有的表在第一次啟動(dòng)的時(shí)候都會(huì)自動(dòng)生成。目前支持sqlserver,mysql,sqlite三種數(shù)據(jù)庫。
##?使用服務(wù)端
###?運(yùn)行服務(wù)端
```
sudo?docker?run?--name?agile_config?-e?adminConsole=true?-e?db:provider=sqlite?-e?db:conn="Data?Source=agile_config.db"?-p?5000:5000?kklldog/agile_config:latest
```
通過docker建立一個(gè)agile_config實(shí)例,其中有3個(gè)環(huán)境變量需要配置:????
1.?adminConsole?配置程序是否為管理控制臺(tái)。如果為true則啟用控制臺(tái)功能,訪問該實(shí)例會(huì)出現(xiàn)管理界面。
2.?db:provider?配置程序的數(shù)據(jù)庫類型。目前程序支持:sqlite,mysql,sqlserver?三種數(shù)據(jù)庫。
3.?db:conn?配置數(shù)據(jù)庫連接串????

###?初始化管理員密碼
第一次遠(yuǎn)行程序需要初始化管理員密碼????

###?節(jié)點(diǎn)
AgileConfig支持多節(jié)點(diǎn)部署,所有的節(jié)點(diǎn)都是平行的。為了簡化部署,AgileConfig并沒有單獨(dú)的控制臺(tái)程序,請直接使用任意一個(gè)節(jié)點(diǎn)作為控制臺(tái)。當(dāng)環(huán)境變量adminConsole=true時(shí),該節(jié)點(diǎn)同時(shí)兼?zhèn)鋽?shù)據(jù)節(jié)點(diǎn)跟控制臺(tái)功能。為了控制臺(tái)能夠管理節(jié)點(diǎn),所以需要在控制臺(tái)配置節(jié)點(diǎn)的信息。
>?注意:即使是作為控制臺(tái)的數(shù)據(jù)節(jié)點(diǎn)同樣需要添加到管理程序,以便管理它。

###?應(yīng)用
AgileConfig支持多應(yīng)用程序接入。需要為每個(gè)應(yīng)用程序配置名稱、ID、秘鑰等信息。

###?配置項(xiàng)
配置完應(yīng)用信息后可以為每個(gè)應(yīng)用配置配置項(xiàng)。配置項(xiàng)支持分組。新添加的配置并不會(huì)被客戶端感知到,需要手工點(diǎn)擊“上線”才會(huì)推送給客戶端。已上線的配置如果發(fā)生修改、刪除、回滾操作,會(huì)實(shí)時(shí)推送給客戶端。版本歷史記錄了配置的歷史信息,可以回滾至任意版本。

###?客戶端
控制臺(tái)可以查看已連接的客戶端。

###?系統(tǒng)日志
系統(tǒng)日志記錄了AgileConfig生產(chǎn)中的一些關(guān)鍵信息。

##?使用客戶端
###?安裝客戶端
```
Install-Package?AgileConfig.Client
```
###?初始化客戶端
以asp.net?core?mvc項(xiàng)目為例:
```
{
??"Logging":?{
????"LogLevel":?{
??????"Default":?"Information",
??????"Microsoft":?"Warning",
??????"Microsoft.Hosting.Lifetime":?"Information"
????}
??},
??"AllowedHosts":?"*",
??//agile_config
??"AgileConfig":?{
????"appId":?"app",
????"secret":?"xxx",
????"nodes":?"http://localhost:5000,http://localhost:5001"http://多個(gè)節(jié)點(diǎn)使用逗號(hào)分隔
??}
}
```
```
???????public?static?IHostBuilder?CreateHostBuilder(string[]?args)?=>
????????????Host.CreateDefaultBuilder(args)
????????????.ConfigureAppConfiguration((context,?config)?=>
????????????{
????????????????//讀取本地配置
????????????????var?localconfig?=?new?ConfigurationBuilder()
?????????????????????????????????.SetBasePath(Directory.GetCurrentDirectory())
?????????????????????????????????.AddJsonFile("appsettings.json").Build();
????????????????//從本地配置里讀取AgileConfig的相關(guān)信息
????????????????var?appId?=?localconfig["AgileConfig:appId"];
????????????????var?secret?=?localconfig["AgileConfig:secret"];
????????????????var?nodes?=?localconfig["AgileConfig:nodes"];
????????????????//new一個(gè)client實(shí)例
????????????????var?configClient?=?new?ConfigClient(appId,?secret,?nodes);
????????????????//使用AddAgileConfig配置一個(gè)新的IConfigurationSource
????????????????config.AddAgileConfig(configClient);
????????????????//找一個(gè)變量掛載client實(shí)例,以便其他地方可以直接使用實(shí)例訪問配置
????????????????ConfigClient?=?configClient;
????????????????//注冊配置項(xiàng)修改事件
????????????????configClient.ConfigChanged?+=?ConfigClient_ConfigChanged;
????????????})
????????????????.ConfigureWebHostDefaults(webBuilder?=>
????????????????{
????????????????????webBuilder.UseStartup<Startup>();
????????????????});
```
##?讀取配置
AgileConfig支持asp.net?core?標(biāo)準(zhǔn)的IConfiguration,跟IOptions模式讀取配置。還支持直接通過AgileConfigClient實(shí)例直接讀?。?/p>
```
public?class?HomeController?:?Controller
????{
????????private?readonly?ILogger<HomeController>?_logger;
????????private?readonly?IConfiguration?_IConfiguration;
????????private?readonly?IOptions<DbConfigOptions>?_dbOptions;
????????public?HomeController(ILogger<HomeController>?logger,?IConfiguration?configuration,?IOptions<DbConfigOptions>?dbOptions)
????????{
????????????_logger?=?logger;
????????????_IConfiguration?=?configuration;
????????????_dbOptions?=?dbOptions;
????????}
????????public?IActionResult?Index()
????????{
????????????return?View();
????????}
????????///?<summary>
????????///?使用IConfiguration讀取配置
????????///?</summary>
????????///?<returns></returns>
????????public?IActionResult?ByIConfiguration()
????????{
????????????var?userId?=?_IConfiguration["userId"];
????????????var?dbConn?=?_IConfiguration["db:connection"];
????????????ViewBag.userId?=?userId;
????????????ViewBag.dbConn?=?dbConn;
????????????return?View();
????????}
????????///?<summary>
????????///?直接使用ConfigClient的實(shí)例讀取配置
????????///?</summary>
????????///?<returns></returns>
????????public?IActionResult?ByInstance()
????????{
????????????var?userId?=?Program.ConfigClient["userId"];
????????????var?dbConn?=?Program.ConfigClient["db:connection"];
????????????ViewBag.userId?=?userId;
????????????ViewBag.dbConn?=?dbConn;
????????????return?View("ByIConfiguration");
????????}
????????///?<summary>
????????///?使用Options模式讀取配置
????????///?</summary>
????????///?<returns></returns>
????????public?IActionResult?ByOptions()
????????{
????????????var?dbConn?=?_dbOptions.Value.connection;
????????????ViewBag.dbConn?=?dbConn;
????????????return?View("ByIConfiguration");
????????}
????}
```
關(guān)注我的公眾號(hào)一起玩轉(zhuǎn)技術(shù)???
