Asp.Net Core自定义配置中心客户端

说明:下面的实例是通过阅读Nacos的SDK源码,提取出来的关键实现 。
Asp.NET core添加一个自定义配置,只要通过IConfigurationBuilder的Add方法,传递一个实现了IConfigurationSource接口实例即可 。
先定义一个NiuBConfigSource,实现接口IConfigurationSource
public class NiuBConfigSource : NiuBOption, IConfigurationSource{public IConfigurationProvider Build(IConfigurationBuilder builder){throw new NotImplementedException();}}这时候,Build方法需要返回一个IConfigurationProvider的实例,那么再来定义一个IConfigurationProvider的实现类,直接继承.Net框架定义好的类ConfigurationProvider,该类实现了IConfigurationProvider接口 。覆写一下Load方法,为后续的配置更新刷新内存配置做准备,重载一个Load方法,传一个键值对进来,调用原来的Load方法,实现对内存的刷新 。
【Asp.Net Core自定义配置中心客户端】public class NiuBConfigProvider : ConfigurationProvider{private Dictionary<string, string> innerCnfiguration = new Dictionary<string, string>();public override void Load(){foreach (string key in innerCnfiguration.Keys){base.Data[key] = innerCnfiguration[key];}base.Load();}internal void Load(Dictionary<string, string> configuration){this.innerCnfiguration = configuration;this.Load();}}这时候NiuBConfigSource就可以返回一个IConfigurationProvider实例了
public class NiuBConfigSource :IConfigurationSource{public IConfigurationProvider Build(IConfigurationBuilder builder){return new NiuBConfigProvider(service);}}为了方便使用,定义一个WebApplicationBuilder的扩展方法UseNiuBConfigure
public static class NiuBConfigProviderExtension{public static IConfigurationBuilder UseNiuBConfigure(this WebApplicationBuilder builder){NiuBConfigSource source = new NiuBConfigSource();IConfigurationBuilder configBuilder = builder.Configuration;return configBuilder.Add(source);}}那么来看一下怎么使用?
var builder = WebApplication.CreateBuilder(args);builder.UseNiuBConfigure();嗯,看起来不错了,那么问题来了,如果配置中心更新了配置,怎么刷新内存配置数据呢?
没错NiuBConfigProvider有个Load的方法 。
我们先改造一下UseNiuBConfigure方法,把配置中心的请求服务地址信息传递进去
public static IConfigurationBuilder UseNiuBConfigure(this WebApplicationBuilder builder, Action<NiuBOption> configure){NiuBOption option= new NiuBOption();configure(option);NiuBConfigSource source = new NiuBConfigSource();IConfigurationBuilder configBuilder = builder.Configuration;return configBuilder.Add(source);}NiuBOption的定义
public class NiuBOption{public string ConfigSectionName { get; set; }public string Host { get; set; }public string Port { get; set; }}定义个监听器
public class Listener{NiuBConfigProvider provider;public Listener(NiuBConfigProvider provider){this.provider = provider;}public void ConfigurationChanged(Dictionary<string, string> configuration){provider.Load(configuration);}}定义一个监听服务
public class NiuBService : INiuBService{// 启动远程监听,比如public NiuBService(){Start();}// 配置中心的代码没有实现,通过该方法进行测试private void grpcAccept(string host, string port, string configSectionName){new ConfigureCenter().ConfigureChanged += configuration=> Configure(configuration);}// 该方法在UseNiuBConfigure方法中服务注入的时候会调用// 根据配置信息,启动远程监听,比如用GRPC的双工通信,socket通信public void Start(){Console.WriteLine("begin listen to xxx监听配置中心");// 如果有新的更新,那么调用Configure方法grpcAccept(this.Option?.Host, this.Option?.Port, this.Option?.ConfigSectionName);}public void Restart(Dictionary<string, string> options){this.Option.Host = options["Host"];this.Option.Host = options["Port"];this.Start();}public NiuBOption Option { get; set; }public List<Listener> Listeners { get; set; } = new List<Listener>();public void Configure(Dictionary<string, string> configuration){foreach (var listener in Listeners){listener.ConfigurationChanged(configuration);}}}现在UseNiuBConfigure方法的实现变成了这样
public static IConfigurationBuilder UseNiuBConfigure(this WebApplicationBuilder builder, Action<NiuBOption> configure){NiuBOption option= new NiuBOption();configure(option);var service= new NiuBService();NiuBConfigSource source = new NiuBConfigSource(service);service.Option= option;builder.Services.addNiuBConfig(service);IConfigurationBuilder configBuilder = builder.Configuration;return configBuilder.Add(source);}NiuBConfigProvider的实现修改为
public class NiuBConfigProvider : ConfigurationProvider{private INiuBService service { get; set; }public NiuBConfigProvider(INiuBService service) {this.service = service;service.Listeners.Add(new Listener(this));}private Dictionary<string, string> innerCnfiguration = new Dictionary<string, string>();public override void Load(){foreach (string key in innerCnfiguration.Keys){base.Data[key] = innerCnfiguration[key];if (key == "ConfigCenterOption") {//热重启配置监听服务service.Restart(innerCnfiguration);}}base.Load();}internal void Load(Dictionary<string, string> configuration){this.innerCnfiguration = configuration;this.Load();}}


推荐阅读