微服務确實是行業的一個趨勢,我自己也在把一些項目往微服務架構遷移。玩微服務架構配置中心是一個繞不過去的東西,有很多大牌的可以選,比如spring-cloud-config,apoll,disconf等等。而我為什麼還要造一個***呢?一來這些都不是.net實作的,我就想試試用.net core實作一個,而且他們也對.net不太友好,也隻有apoll提供了官方的.net用戶端。二來這些元件都太重量級了,比如apoll,光跑起來就要部署多個節點(admin,portal,meta sevice)還要依賴eureka。很多舊的項目往微服務遷移的時候并不是一下次全部調整完成的,可能是一步步來的,比如先把所有的服務都容器化,并沒有使用微服務全家桶。而且有的項目也不需要微服務全家桶,畢竟微服務不是銀彈,很多項目單體結構就足夠了,有些項目傳統的SOA架構也可以了。(唠叨一句,那種毫無流量毫無并發的項目,幾人幾天就搞完的強上微服務真的好嗎?)但是這些項目也可能是分布式的,容器化部署的,那麼這些項目我覺得也是需要配置中心的,因為在分布式、容器化環境下更改配置實在是太麻煩了。可以說配置中心并不是微服務獨有的。基于以上原因我提煉了一些配置中心必備的功能,做的盡量簡單(陋),開發了AgileConfig,為.net core的生态盡一份綿薄之力。
Github求star:AgileConfig
AgileConfig
這是一個基于.net core開發的輕量級配置中心。
- 部署簡單,最少隻需要一個資料節點,支援docker部署
- 支援多節點分布式部署來保證高可用
- 配置支援按應用隔離,應用内配置支援分組隔離
- 使用長連接配接技術,配置資訊實時推送至用戶端
- 支援IConfiguration,IOptions模式讀取配置,原程式幾乎可以不用改造
- 配置修改支援版本記錄,随時復原配置
- 如果所有節點都故障,用戶端支援從本地緩存讀取配置
架構

AgileConfig的架構比較簡單,主要是分3塊:
用戶端
用戶端程式是使用netstandard2.0開發的一個類庫,友善.net core程式接入,nuget搜agileconfig.client就可以安裝。可以在啟動用戶端的時候配置多個節點的位址,用戶端會随機挑選一個進行連接配接,連接配接成功後會維持一個websocket長連接配接。如果連接配接的節點發生故障導緻連接配接中斷,用戶端會繼續随機一個節點進行連接配接,直到連接配接成功。
節點、管理程式
節點是使用asp.net core開發的一個服務。為了部署簡單,直接把管理程式跟節點服務合二為一了。任何一個節點都可以在啟動的時候配置環境變量開啟管理程式功能。
資料庫
使用資料庫來存儲資料,目前支援Sqlserver, Mysql, Sqlite 三種資料庫。因為服務端使用EF Core架構通路資料,原則上隻要EF Core支援的資料庫,節點就可以很友善的支援它。
部署服務端
初始化資料庫
使用者隻需要手工建一個空庫,所有的表在第一次啟動的時候都會自動生成。目前支援sqlserver,mysql,sqlite三種資料庫。
使用服務端
運作服務端
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建立一個agile_config執行個體,其中有3個環境變量需要配置:
- adminConsole 配置程式是否為管理控制台。如果為true則啟用控制台功能,通路該執行個體會出現管理界面。
- db:provider 配置程式的資料庫類型。目前程式支援:sqlite,mysql,sqlserver 三種資料庫。
- db:conn 配置資料庫連接配接串
初始化管理者密碼
第一次遠行程式需要初始化管理者密碼
節點
AgileConfig支援多節點部署,所有的節點都是平行的。為了簡化部署,AgileConfig并沒有單獨的控制台程式,請直接使用任意一個節點作為控制台。當環境變量adminConsole=true時,該節點同時兼備資料節點跟控制台功能。為了控制台能夠管理節點,是以需要在控制台配置節點的資訊。
注意:即使是作為控制台的資料節點同樣需要添加到管理程式,以便管理它。
應用
AgileConfig支援多應用程式接入。需要為每個應用程式配置名稱、ID、秘鑰等資訊。
配置項
配置完應用資訊後可以為每個應用配置配置項。配置項支援分組。新添加的配置并不會被用戶端感覺到,需要手工點選“上線”才會推送給用戶端。已上線的配置如果發生修改、删除、復原操作,會實時推送給用戶端。版本曆史記錄了配置的曆史資訊,可以復原至任意版本。
用戶端
控制台可以檢視已連接配接的用戶端。
系統日志
系統日志記錄了AgileConfig生産中的一些關鍵資訊。
使用用戶端
安裝用戶端
Install-Package AgileConfig.Client
初始化用戶端
以asp.net core mvc項目為例:
修改appsettings.json
{
"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"//多個節點使用逗号分隔
}
}
修改program:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
//讀取本地配置
var localconfig = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json").Build();
//從本地配置裡讀取AgileConfig的相關資訊
var appId = localconfig["AgileConfig:appId"];
var secret = localconfig["AgileConfig:secret"];
var nodes = localconfig["AgileConfig:nodes"];
//new一個client執行個體
var configClient = new ConfigClient(appId, secret, nodes);
//使用AddAgileConfig配置一個新的IConfigurationSource
config.AddAgileConfig(configClient);
//找一個變量挂載client執行個體,以便其他地方可以直接使用執行個體通路配置
ConfigClient = configClient;
//注冊配置項修改事件
configClient.ConfigChanged += ConfigClient_ConfigChanged;
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
讀取配置
AgileConfig支援asp.net core 标準的IConfiguration,跟IOptions模式讀取配置。還支援直接通過AgileConfigClient執行個體直接讀取:
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的執行個體讀取配置
/// </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");
}
}
關注我的公衆号一起玩轉技術