<返回更多

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

2023-02-23  今日头条  不知名程序猿
加入收藏

说明:下面的实例是通过阅读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方法,实现对内存的刷新。

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

NiuBConfigSource把Service传递进去

    public class NiuBConfigSource : NiuBOption, IConfigurationSource
    {
        private INiuBService service;
        public NiuBConfigSource(INiuBService service)
        {
            this.service = service;
        }
        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new NiuBConfigProvider(service);
        }
    }

事情搞完了,下面来测试一下,由于注册中心没有实现,下面来模拟一下

       // 配置中心的代码没有实现,通过该方法模拟监听
        private void grpcAccept(string host, string port, string configSectionName)
        {
            ConfigureCenter.ConfigureChanged += configuration=> Configure(configuration);
        }

ConfigureCenter的实现

    public class ConfigureCenter
    {
        public ConfigureCenter() { }
        public event Action<Dictionary<string, string>> ConfigureChanged;

        public void PublishConfig(Dictionary<string, string> config)
        {
            if (this.ConfigureChanged != null)
            {
                ConfigureChanged(config);
            }
        }
    }

模拟配置中心发布了新的配置

var service= app.Services.GetService<INiuBService>();

service.ConfigureCenter.PublishConfig(new Dictionary<string, string>() {
    { "OrderService","{"Host":"http://niubi.com/api/order","descript":"订单服务地址"}"}
});

通过API查看是否能获取到配置中心发布的配置

    [Route("api/[Controller]")]
    public class OrderController : ControllerBase
    {
        public IConfiguration Configuration { get; set; }
 
        public OrderController(IConfiguration configuration )
        {
            this.Configuration = configuration;
            
        }
        [HttpGet]
        public string Get()
        {
            var value= Configuration["OrderService"];
            return value == null ?  "Empty": value;
        }
    }

请求结果

 

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>