重新整理 .net core 實踐篇—————配置系統之簡單配置中心[十一]

不問前世發表於2021-06-05

前言

市面上已經有很多配置中心整合工具了,故此不會去實踐某個框架。

下面連結是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();
}

這裡只是作為演示,實際上我們可以通過在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;

直接返回本身即可。看到這裡我們有時候也就不用太古板了,不是說非要分開兩個類來實現。完全可以作為一個整體,也是極好的。

上述只是個人整理,如有錯誤,望請指點。

配置大概就整理到這裡,後面寫服務相關的,當然也會使用到前面這些微薄的原理(沒有深入分析),就知道為什麼服務配置要那麼寫了。

下一節 服務與配置之間。

相關文章