189 8069 5689

如何在.NetCore中自定义配置源-创新互联

这篇文章给大家介绍如何在.Net Core中自定义配置源,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

为牡丹等地区用户提供了全套网页设计制作服务,及牡丹网站建设行业解决方案。主营业务为成都网站设计、成都做网站、牡丹网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

模拟配置中心


我们新建一个asp.net core webapi站点来模拟配置中心服务,端口配置到5000,并添加相应的controller来模拟配置中心对外的接口。

  [Route("api/[controller]")]
 [ApiController]
 public class ConfigsController : ControllerBase
 {
  public List> Get()
  {
   var configs = new List>();
   configs.Add(new KeyValuePair("SecretKey","1238918290381923"));
   configs.Add(new KeyValuePair("ConnectionString", "user=123;password=123;server=."));

   return configs;
  }
 }

添加一个configscontroller,并修改Get方法,返回2个配置键值对。

如何在.Net Core中自定义配置源

访问下/api/configs看下返回是否正确

自定义配置源


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


新建一个asp.net core mvc站点来模拟客户端程序。

MyConfigProvider


 public class MyConfigProvider : ConfigurationProvider
 {
  /// 
  /// 尝试从远程配置中心读取配置信息
  /// 
  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>>(response);

   Data = new ConcurrentDictionary();

   configs.ForEach(c =>
   {
    Data.Add(c);
   });
  }
 
 }

新建一个MyConfigProvider的类,这个类从ConfigurationProvider继承,并重写其中的Load方法。使用HttpClient从配置中心读取信息后,进行反序列化,并把配置转换为字典。这里注意一下,虽然Data的类型为IDictionary,但是这里实例化对象的时候使用了ConcurrentDictionary类,因为Dictionary是非线程安全的,如果进行多线程读写会出问题。

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();
 }

在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";
}

 SecretKey: @ViewBag.SecretKey

 ConnectionString: @ViewBag.ConnectionString

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

运行一下

如何在.Net Core中自定义配置源

先运行配置中心站点再运行一下网站,首页出现了我们在配置中心定义的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;
  }

  /// 
  /// 尝试从远程配置中心读取配置信息,当成功从配置中心读取信息的时候把配置写到本地的myconfig.json文件中,当配置中心无法访问的时候尝试从本地文件恢复配置。
  /// 
  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>>(response);

   Data = new ConcurrentDictionary();

   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);
  }
 }

关于如何在.Net Core中自定义配置源就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。


本文标题:如何在.NetCore中自定义配置源-创新互联
本文URL:http://cdxtjz.com/article/pjsoo.html

其他资讯