数码控科技猎奇Iphone动漫星座游戏电竞lolcosplay王者荣耀攻略allcnewsBLOGNEWSBLOGASKBLOGBLOGZSK全部技术问答问答技术问答it问答代码软件新闻开发博客电脑/网络手机/数码笔记本电脑互联网操作系统软件硬件编程开发360产品资源分享电脑知识文档中心IT全部全部分类全部分类技术牛文全部分类教程最新网页制作cms教程平面设计媒体动画操作系统网站运营网络安全服务器教程数据库工具网络安全软件教学vbscript正则表达式javascript批处理更多»编程更新教程更新游戏更新allitnewsJava新闻网络医疗信息化安全创业站长电商科技访谈域名会议专栏创业动态融资创投创业学院 / 产品经理创业公司人物访谈营销开发数据库服务器系统虚拟化云计算嵌入式移动开发作业作业1常见软件all电脑网络手机数码生活游戏体育运动明星影音休闲爱好文化艺术社会民生教育科学医疗健康金融管理情感社交地区其他电脑互联网软件硬件编程开发360相关产品手机平板其他电子产品摄影器材360硬件通讯智能设备购物时尚生活常识美容塑身服装服饰出行旅游交通汽车购房置业家居装修美食烹饪单机电脑游戏网页游戏电视游戏桌游棋牌游戏手机游戏小游戏掌机游戏客户端游戏集体游戏其他游戏体育赛事篮球足球其他运动球类运动赛车健身运动运动用品影视娱乐人物音乐动漫摄影摄像收藏宠物幽默搞笑起名花鸟鱼虫茶艺彩票星座占卜书画美术舞蹈小说图书器乐声乐小品相声戏剧戏曲手工艺品历史话题时事政治就业职场军事国防节日风俗法律法规宗教礼仪礼节自然灾害360维权社会人物升学入学人文社科外语资格考试公务员留学出国家庭教育学习方法语文物理生物工程学农业数学化学健康知识心理健康孕育早教内科外科妇产科儿科皮肤科五官科男科整形中医药品传染科其他疾病医院两性肿瘤科创业投资企业管理财务税务银行股票金融理财基金债券保险贸易商务文书国民经济爱情婚姻家庭烦恼北京上海重庆天津黑龙江吉林辽宁河北内蒙古山西陕西宁夏甘肃青海新疆西藏四川贵州云南河南湖北湖南山东江苏浙江安徽江西福建广东广西海南香港澳门台湾海外地区

.Net Core自定义配置源从配置中心读取配置的方法

来源:脚本之家  责任编辑:小易  

前言

配置,几乎所有的应用程序都离不开它。.Net Framework时代我们使用App.config、Web.config,到了.Net Core的时代我们使用appsettings.json,这些我们再熟悉不过了。然而到了容器化、微服务的时代,这些本地文件配置有的时候就不太合适了。当你把本地部署的服务搬到docker上后,你会发现要修改一个配置文件变的非常麻烦。你不得不通过宿主机进入容器内部来修改文件,也许容器内还不带vi等编辑工具,你连看都不能看,改都不能。更别说当你启动多个容器实例来做分布式应用的时候,一个个去修改容器的配置,这简直要命了。

因为这些原因,所以“配置中心”就诞生了。配置中心是微服务的基础设施,它对配置进行集中的管理并对外暴露接口,当应用程序需要的时候通过接口读取。配置通常为Key/Value模式,然后通过http接口暴露。好了,配置中心不多说了,感觉要偏了,这次是介绍怎么自定义一个配置源从配置中心读取配置。废话不多说直接上代码吧。

模拟配置中心

我们新建一个asp.net core webapi站点来模拟配置中心服务,端口配置到5000,并添加相应的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看下返回是否正确

自定义配置源

从现在开始我们真正开始来定义一个自定义的配置源然后当程序启动的时候从配置中心读取配置文件信息,并提供给后面的代码使用配置。

新建一个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从配置中心读取信息后,进行反序列化,并把配置转换为字典。这里注意一下,虽然Data的类型为IDictionary<string,string>,但是这里实例化对象的时候使用了ConcurrentDictionary<string, string>类,因为Dictionary<string,string>是非线程安全的,如果进行多线程读写会出问题。

MyConfigSource

 public class MyConfigSource : IConfigurationSource
 {
  public IConfigurationProvider Build(IConfigurationBuilder builder)
  {
   return new MyConfigProvider();
  }
 }

新建一个MyConfigSource的类,这个类实现IConfigurationSource接口,IConfigurationSource接口只有一个Build方法,返回值为IConfigurationProvider,我们刚才定义的MyConfigProvider因为继承自ConfigurationProvider所以已经实现了IConfigurationProvider,我们直接new一个MyConfigProvider并返回。

MyConfigBuilderExt

 public static class MyConfigBuilderExt
 {
  public static IConfigurationBuilder AddMyConfig(
   this IConfigurationBuilder builder
   )
  {
   return builder.Add(new MyConfigSource());
  }
 }

给IConfigurationBuilder定义一个AddMyConfig的扩展方法,跟.Net Core自带的几个配置源使用风格保持一致。当调用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的匿名委托方法中调用AddMyConfig扩展方法,这样程序启动的时候会自动使用MyConfigSource源并从配置中心读取配置到本地应用程序。

修改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通过构造函数注入进去,在Index Action方法中读取配置,并赋值给ViewBag

修改Index视图

 @{
 ViewData["Title"] = "Test my config";
}

<h3>
 SecretKey: @ViewBag.SecretKey
</h3>
<h3>
 ConnectionString: @ViewBag.ConnectionString
</h3>

修改Index视图的代码,把配置信息从ViewBag中读取出来并在网页上展示。

运行一下

先运行配置中心站点再运行一下网站,首页出现了我们在配置中心定义的SecretKey跟ConnectionString信息,表示我们的程序成功的从配置中心读取了配置信息。我们的自定义配置源已经能够成功运行了。

改进

以上配置源虽然能够成功运行,但是仔细看的话显然它有2个比较大的问题。

  • 配置中心的服务地址是写死在类里的。我们的配置中心很有可能会修改ip或者域名,写死在代码里显然不是高明之举,所以我们还是需要保留本地配置文件,把配置中心的服务地址写到本地配置文件中。
  • 配置中心作为微服务的基础设施一旦故障会引发非常严重的后果,新启动或者重启的客户端会无法正常启动。如果我们在配置中心正常的时候冗余一份配置在本地,当配置中心故障的时候从本地读取配置,至少可以保证一部分客户端程序能够正常运行。
{
 "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文件中,当配置中心无法访问的时候尝试从本地文件恢复配置。
  /// </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);
  }
 }

修改MyConfigProvider,修改构造函数,通过JsonConfigurationProvider从本地读取appsettings.json中的myconfigServer配置信息。新增WriteToLocal方法把配置中心返回的json数据写到本地文件中。新增ReadFromLocal方法,从本地文件读取json信息。

再次运行

先运行配置中心站点,再运行客户端网站,可以看到配置信息展示到首页界面上。关闭配置中心客跟客户端网站,并且重启客户端网站依然能够展示配置信息,说明自定义配置源当配置中心故障的时候成功从本地文件恢复了配置。图跟上面的图是一致的,就不贴了。

总结

通过以上我们定义了一个比较简单的自定义配置源,它能够通过http从配置中心读取配置,并且提供了同传统json配置文件一致的使用风格,最大程度的复用旧代码,减少因为引入配置中心而大规模改动代码。我们从上面的代码可以更清楚的知道.Net Core的配置源是如何工作的。ConfigurationSource只是ConfigurationProvider的建造器。真正完成配置加载、查找工作的是ConfigurationProvider。

以上代码还是演示级别的代码,还有很多改进的空间,比如http访问失败的重试,我们可以使用polly重构;比如支持定时从配置中心刷新配置等,有兴趣可以自己去实践一下。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

您可能感兴趣的文章:


  • 本文相关:
  • asp.net core配置教程之读取配置信息
  • .netcore获取json和xml格式的配置信息
  • .net core简单读取json配置文件
  • 实现core文件自动生成配置文件的方法
  • asp.net core mvc 配置全局路由前缀
  • asp.net core中灵活的配置方式详解
  • ubuntu16.04系统配置.net core环境
  • 如何在asp.net core类库项目中读取配置文件详解
  • .net core2.1如何获取自定义配置文件信息详解
  • .net core读取配置文件方式详细总结
  • asp.net+jquery jsonp使用方法
  • asp.net core 1.0 部署 https(.net core 1.0)
  • 开启sqlserver数据库缓存依赖优化网站性能
  • asp.net缓存管理的几种方法
  • .net下quartz.net的使用方法
  • asp.net使用httpwebrequest读取远程网页源代码
  • asp.net发送邮件示例分享
  • c#多线程singleton(单件)模式模板
  • gridview checkbox从服务器端和客户端两个方面实现全选和反选
  • c#实现根据网络ip显示地理位置功能示例
  • 免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved