前言

市面上已经有很多配置中心集成工具了,故此不会去实践某个框架。

下面链接是apollo 官网的教程,实在太详细了,本文介绍一下扩展数据源,和简单翻翻阅一下apollo 关键部分。

apollo 服务配置:
https://github.com/ctripcorp/apollo/wiki/.Net客户端使用指南
apollo .net 客户端配置:
https://github.com/ctripcorp/apollo.net/tree/dotnet-core/Apollo.Configuration

正文

扩展数据源

经过前面的系列的源码解读,我们知道我们需要去实现IConfigurationSource,IConfigurationProvider。

他们的关系是IConfigurationSource build 方法会构建出IConfigurationProvider,IConfigurationProvider 会为 IConfigurationRoot 提供数据源。

好的,那么开始吧。
RemoteConfigurationSource 实现 IConfigurationSource:

public class RemoteConfigurationSource : IConfigurationSource
{
	public RemoteConfigurationProvider _provider;
	public RemoteConfigurationProvider Provider
	{
		get
		{
			if (_provider == null)
			{
				_provider = new RemoteConfigurationProvider();
			}
			return _provider;
		}
	}

	public IConfigurationProvider Build(IConfigurationBuilder builder)
	{
		return this.Provider;
	}
}

IConfigurationProvider 继承ConfigurationProvider:

public class RemoteConfigurationProvider : ConfigurationProvider
{
	public RemoteConfigurationProvider():base()
	{
	}

	public override  void Load()
	{
		this.Data["name"] = "zhangshan";
		Load(false);
	}

	public void Load(bool reload)
	{
		if (reload)
		{
			this.OnReload();
		}
	}
}

这里没有继承IConfigurationProvider而是继承ConfigurationProvider的原因,是因为ConfigurationProvider实现基于字典的数据源实现,这里演示比较方便。

static void Main(string[] args)
{
	IConfigurationBuilder builder = new ConfigurationBuilder();
	var selfSource = new RemoteConfigurationSource();

	builder.Add(selfSource);

	var root = builder.Build();

	Console.WriteLine($"name: {root["name"]}");

	ChangeToken.OnChange(() => root.GetReloadToken(), () =>
	{
		Console.WriteLine($"reload name: {root["name"]}");
	});

	selfSource.Provider.Set("name","lisi");
	selfSource.Provider.Load(true);
	Console.ReadKey();
}

重新整理 .net core 实践篇—————配置系统之简单配置中心[十一]-LMLPHP

这里只是作为演示,实际上我们可以通过在RemoteConfigurationProvider 做监听,然后收到通知后,进行reload 调用即可,在configurationProvider中的reload如下:

private ConfigurationReloadToken _reloadToken = new ConfigurationReloadToken();
protected void OnReload()
{
	ConfigurationReloadToken previousToken = Interlocked.Exchange(ref _reloadToken, new ConfigurationReloadToken());
	previousToken.OnReload();
}

触发令牌更新,然后令牌会触发回调。

那么来看下apollo 第三方组件怎么写的吧。

引入这个包: Com.Ctrip.Framework.apollo.Configuration

public class ApolloConfigurationProvider : ConfigurationProvider, IRepositoryChangeListener, IConfigurationSource
{
	internal string? SectionKey { get; }
	internal IConfigRepository ConfigRepository { get; }
	private Task? _initializeTask;

	public ApolloConfigurationProvider(string? sectionKey, IConfigRepository configRepository)
	{
		SectionKey = sectionKey;
		ConfigRepository = configRepository;
		ConfigRepository.AddChangeListener(this);
		_initializeTask = ConfigRepository.Initialize();
	}

	public override void Load()
	{
		Interlocked.Exchange(ref _initializeTask, null)?.ConfigureAwait(false).GetAwaiter().GetResult();

		SetData(ConfigRepository.GetConfig());
	}

	protected virtual void SetData(Properties properties)
	{
		var data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		foreach (var key in properties.GetPropertyNames())
		{
			if (string.IsNullOrEmpty(SectionKey))
				data[key] = properties.GetProperty(key) ?? string.Empty;
			else
				data[$"{SectionKey}{ConfigurationPath.KeyDelimiter}{key}"] = properties.GetProperty(key) ?? string.Empty;
		}

		Data = data;
	}

	void IRepositoryChangeListener.OnRepositoryChange(string namespaceName, Properties newProperties)
	{
		SetData(newProperties);

		OnReload();
	}

	IConfigurationProvider IConfigurationSource.Build(IConfigurationBuilder builder) => this;
}

里面有这个OnRepositoryChange 监听,如果收到监听信息然后就触发设置数据,然后调用OnReload 触发令牌过期,也就是触发通知。

有些人肯定问啊,肯定要有IconfigurationSource啊,在哪呢? 看这个设计ApolloConfigurationProvider 继承了IConfigurationSource接口。

ApolloConfigurationProvider实现的build(上面贴了)如下:

IConfigurationProvider IConfigurationSource.Build(IConfigurationBuilder builder) => this;

直接返回本身即可。看到这里我们有时候也就不用太古板了,不是说非要分开两个类来实现。完全可以作为一个整体,也是极好的。

上述只是个人整理,如有错误,望请指点。

配置大概就整理到这里,后面写服务相关的,当然也会使用到前面这些微薄的原理(没有深入分析),就知道为什么服务配置要那么写了。

下一节 服务与配置之间。

06-05 13:22