写在前面
经过前面三篇关于.NET Core Configuration的文章之后,本篇文章主要讨论如何扩展一个Configuration组件出来。如果前面三篇文章没有看到,可以点击如下地址访问
-
.NET Core 3.0之深入源码理解Configuration(一)
-
.NET Core 3.0之深入源码理解Configuration(二)
-
.NET Core 3.0之深入源码理解Configuration(三)
了解了Configuration的源码后,再去扩展一个组件就会比较简单,接下来我们将在.NET Core 3.0-preview5的基础上创建一个基于Consul的配置组件。
相信大家对Consul已经比较了解了,很多项目都会使用Consul作为配置中心,此处也不做其他阐述了,主要是讲一下,创建Consul配置扩展的一些思路。使用Consul配置功能时,我们可以将信息转成JSON格式后再存储,那么我们在读取的时候,在体验上就像是从读取JSON文件中读取一样。
开发前的准备
初始化Consul
假设你已经安装并启动了Consul,我们打开Key/Value功能界面,创建两组配置选项出来,分别是commonservice和userservice,如下图所示
配置值采用JSON格式
实现思路
我们知道在Configuration整个的设计框架里,比较重要的类ConfigurationRoot,内部又有一个IConfigurationProvider集合属性,也就是说我们追加IConfigurationProvider实例最终也会被放到到该集合中,如下图所示
该项目中,我使用到了一个已经封装好的Consul(V0.7.2.6)类库,同时基于.NET Core关于Configuration的设计风格,做如下的框架设计
考虑到我会在该组件内部创建ConsulClient实例,所以对ConsulClient构造函数的一部分参数做了抽象提取,并添加到了IConsulConfigurationSource中,以增强该组件的灵活性。
之前说过,Consul中的配置信息是以JSON格式存储的,所以此处使用到了Microsoft.Extensions.Configuration.Json.JsonConfigurationFileParser,用以将JSON格式的信息转换为Configuration的通用格式Key/Value。
核心代码
IConsulConfigurationSource
1: /// <summary>
2: /// ConsulConfigurationSource
3: /// </summary>
4: public interface IConsulConfigurationSource : IConfigurationSource
5: {
6: /// <summary>
7: /// CancellationToken
8: /// </summary>
9: CancellationToken CancellationToken { get; }
10:
11: /// <summary>
12: /// Consul构造函数实例,可自定义传入
13: /// </summary>
14: Action<ConsulClientConfiguration> ConsulClientConfiguration { get; set; }
15:
16: /// <summary>
17: /// Consul构造函数实例,可自定义传入
18: /// </summary>
19: Action<HttpClient> ConsulHttpClient { get; set; }
20:
21: /// <summary>
22: /// Consul构造函数实例,可自定义传入
23: /// </summary>
24: Action<HttpClientHandler> ConsulHttpClientHandler { get; set; }
25:
26: /// <summary>
27: /// 服务名称
28: /// </summary>
29: string ServiceKey { get; }
30:
31: /// <summary>
32: /// 可选项
33: /// </summary>
34: bool Optional { get; set; }
35:
36: /// <summary>
37: /// Consul查询选项
38: /// </summary>
39: QueryOptions QueryOptions { get; set; }
40:
41: /// <summary>
42: /// 重新加载延迟时间,单位是毫秒
43: /// </summary>
44: int ReloadDelay { get; set; }
45:
46: /// <summary>
47: /// 是否在配置改变的时候重新加载
48: /// </summary>
49: bool ReloadOnChange { get; set; }
50: }
ConsulConfigurationSource
该类提供了一个构造函数,用于接收ServiceKey和CancellationToken实例
1: public ConsulConfigurationSource(string serviceKey, CancellationToken cancellationToken)
2: {
3: if (string.IsNullOrWhiteSpace(serviceKey))
4: {
5: throw new ArgumentNullException(nameof(serviceKey));
6: }
7:
8: this.ServiceKey = serviceKey;
9: this.CancellationToken = cancellationToken;
10: }
其build()方法也比较简单,主要是初始化ConsulConfigurationParser实例
1: public IConfigurationProvider Build(IConfigurationBuilder builder)
2: {
3: ConsulConfigurationParser consulParser = new ConsulConfigurationParser(this);
4:
5: return new ConsulConfigurationProvider(this, consulParser);
6: }
ConsulConfigurationParser
该类比较复杂,主要实现Consul配置的获取、监控以及容错处理,公共方法源码如下
1: /// <summary>
2: /// 获取并转换Consul配置信