您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何在.Net Core中自定義配置源,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
模擬配置中心
我們新建一個asp.net core webapi站點來模擬配置中心服務(wù),端口配置到5000,并添加相應(yīng)的controller來模擬配置中心對外的接口。
[Route("api/[controller]")] [ApiController] public class ConfigsController : ControllerBase { public List<KeyValuePair<string,string>> Get() { var configs = new List<KeyValuePair<string, string>>(); configs.Add(new KeyValuePair<string, string>("SecretKey","1238918290381923")); configs.Add(new KeyValuePair<string, string>("ConnectionString", "user=123;password=123;server=.")); return configs; } }
添加一個configscontroller,并修改Get方法,返回2個配置鍵值對。
訪問下/api/configs看下返回是否正確
自定義配置源
從現(xiàn)在開始我們真正開始來定義一個自定義的配置源然后當程序啟動的時候從配置中心讀取配置文件信息,并提供給后面的代碼使用配置。
新建一個asp.net core mvc站點來模擬客戶端程序。
MyConfigProvider
public class MyConfigProvider : ConfigurationProvider { /// <summary> /// 嘗試從遠程配置中心讀取配置信息 /// </summary> public async override void Load() { var response = ""; try { var serverAddress = "http://localhost:5000"; var client = new HttpClient(); client.BaseAddress = new Uri(serverAddress); response = await client.GetStringAsync("/api/configs"); } catch (Exception ex) { //write err log } if (string.IsNullOrEmpty(response)) { throw new Exception("Can not request configs from remote config center ."); } var configs = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(response); Data = new ConcurrentDictionary<string, string>(); configs.ForEach(c => { Data.Add(c); }); } }
新建一個MyConfigProvider的類,這個類從ConfigurationProvider繼承,并重寫其中的Load方法。使用HttpClient從配置中心讀取信息后,進行反序列化,并把配置轉(zhuǎn)換為字典。這里注意一下,雖然Data的類型為IDictionary<string,string>,但是這里實例化對象的時候使用了ConcurrentDictionary<string, string>類,因為Dictionary<string,string>是非線程安全的,如果進行多線程讀寫會出問題。
MyConfigSource
public class MyConfigSource : IConfigurationSource { public IConfigurationProvider Build(IConfigurationBuilder builder) { return new MyConfigProvider(); } }
新建一個MyConfigSource的類,這個類實現(xiàn)IConfigurationSource接口,IConfigurationSource接口只有一個Build方法,返回值為IConfigurationProvider,我們剛才定義的MyConfigProvider因為繼承自ConfigurationProvider所以已經(jīng)實現(xiàn)了IConfigurationProvider,我們直接new一個MyConfigProvider并返回。
MyConfigBuilderExt
public static class MyConfigBuilderExt { public static IConfigurationBuilder AddMyConfig( this IConfigurationBuilder builder ) { return builder.Add(new MyConfigSource()); } }
給IConfigurationBuilder定義一個AddMyConfig的擴展方法,跟.Net Core自帶的幾個配置源使用風(fēng)格保持一致。當調(diào)用AddMyConfig的時候給IConfigurationBuilder實例添加一個MyConfigSource的源。
使用配置源
在Program中添加MyConfigSource
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, configBuiler) => { configBuiler.AddMyConfig(); }) .UseStartup<Startup>(); }
在ConfigureAppConfiguration的匿名委托方法中調(diào)用AddMyConfig擴展方法,這樣程序啟動的時候會自動使用MyConfigSource源并從配置中心讀取配置到本地應(yīng)用程序。
修改HomeController
public class HomeController : Controller { IConfiguration _configuration; public HomeController(IConfiguration configuration) { _configuration = configuration; } public IActionResult Index() { var secretKey = _configuration["SecretKey"]; var connectionString = _configuration["ConnectionString"]; ViewBag.SecretKey = secretKey; ViewBag.ConnectionString = connectionString; return View(); } }
修改homecontroller,把IConfiguration通過構(gòu)造函數(shù)注入進去,在Index Action方法中讀取配置,并賦值給ViewBag
修改Index視圖
@{ ViewData["Title"] = "Test my config"; } <h4> SecretKey: @ViewBag.SecretKey </h4> <h4> ConnectionString: @ViewBag.ConnectionString </h4>
修改Index視圖的代碼,把配置信息從ViewBag中讀取出來并在網(wǎng)頁上展示。
運行一下
先運行配置中心站點再運行一下網(wǎng)站,首頁出現(xiàn)了我們在配置中心定義的SecretKey跟ConnectionString信息,表示我們的程序成功的從配置中心讀取了配置信息。我們的自定義配置源已經(jīng)能夠成功運行了。
改進
以上配置源雖然能夠成功運行,但是仔細看的話顯然它有2個比較大的問題。
配置中心的服務(wù)地址是寫死在類里的。我們的配置中心很有可能會修改ip或者域名,寫死在代碼里顯然不是高明之舉,所以我們還是需要保留本地配置文件,把配置中心的服務(wù)地址寫到本地配置文件中。
配置中心作為微服務(wù)的基礎(chǔ)設(shè)施一旦故障會引發(fā)非常嚴重的后果,新啟動或者重啟的客戶端會無法正常啟動。如果我們在配置中心正常的時候冗余一份配置在本地,當配置中心故障的時候從本地讀取配置,至少可以保證一部分客戶端程序能夠正常運行。
{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "myconfigServer": "http://localhost:5000" }
修改本地appsettings.json文件,添加myconfigServer的配置信息。
public class MyConfigProvider : ConfigurationProvider { private string _serverAddress; public MyConfigProvider() { var jsonConfig = new JsonConfigurationSource(); jsonConfig.FileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory()); jsonConfig.Path = "appsettings.json"; var jsonProvider = new JsonConfigurationProvider(jsonConfig); jsonProvider.Load(); jsonProvider.TryGet("myconfigServer", out string serverAddress); if (string.IsNullOrEmpty(serverAddress)) { throw new Exception("Can not find myconfigServer's address from appsettings.json"); } _serverAddress = serverAddress; } /// <summary> /// 嘗試從遠程配置中心讀取配置信息,當成功從配置中心讀取信息的時候把配置寫到本地的myconfig.json文件中,當配置中心無法訪問的時候嘗試從本地文件恢復(fù)配置。 /// </summary> public async override void Load() { var response = ""; try { var client = new HttpClient(); client.BaseAddress = new Uri(_serverAddress); response = await client.GetStringAsync("/api/configs"); WriteToLocal(response); } catch (Exception ex) { //write err log response = ReadFromLocal(); } if (string.IsNullOrEmpty(response)) { throw new Exception("Can not request configs from remote config center ."); } var configs = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(response); Data = new ConcurrentDictionary<string, string>(); configs.ForEach(c => { Data.Add(c); }); } private void WriteToLocal(string resp) { var file = Directory.GetCurrentDirectory() + "/myconfig.json"; File.WriteAllText(file,resp); } private string ReadFromLocal() { var file = Directory.GetCurrentDirectory() + "/myconfig.json"; return File.ReadAllText(file); } }
關(guān)于如何在.Net Core中自定義配置源就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。