.NET Core etcd 配置源
etcd 是一個高可用的 Key/Value 存儲系統,主要用于共享配置和服務發現,和目前比較主流的配置中心(如:Spring Cloud Config、Apollo、Consul、Nacos)、注冊中心(如:Zookeeper、Eureka、Consul、Nacos)功能上有很多相似之處,關于各框架之間的對比可以網上搜索。
ectd 的搭建不是本文的重點,本文將基于 ectd v3 版本來測試,為了方便查看效果,還將借助 ?etcd-manage 可視化管理工具。
etcd 客戶端
既然程序需要獲取 etcd 中的配置信息,那就必須有對 etcd 操作的客戶端代碼。官方提供了調用 etcd 服務的 gRPC 接口定義,而 gRPC 有一個特點就是跨語言,所以如果項目中需要引入 etcd 作為配置或注冊中心,完全可以直接基于 gRPC 接口定義文件生成對應語言的客戶端代碼實現遠程調用。而對于目前來說,客戶端代碼的封裝在 Github 上早已有實現,如:Java 的 jetcd,.NET 的 dotnet-etcd ,所以我們完全可以站在巨人的肩膀上玩耍。
.NET Core 集成 etcd
關于如何在 .NET 中操作 etcd ,我們可以根據 dotnet-etcd 的介紹來進行一系列測試,本文主要介紹 .NET Core 基于 etcd 實現服務的配置管理。既然客戶端代碼有現成的,那是不是直接 NuGet 安裝 dotnet-etcd 后,通過方法調用拿到某些 key 的值使用就好了?當然這么玩沒有任何問題,但個人感覺這樣在程序上看來有些松散,畢竟 .NET Core 有可擴展性的配置體系,最終都通過 ConfigurationBuilder 構造供使用。
基于上篇文章 .NET Core 自定義配置源 的介紹,接下來將使用 etcd 作為自定義配置源,所以為了接下來理解順利,請 務必閱讀 過 ?.NET Core 自定義配置源 。
實現目標
可通過 Configuration 對象進行配置信息讀取;
etcd 配置中心對相關配置進行變更時,能自動刷新配置;
前面提到了 etcd 是一個 Key/Value 存儲系統,我們可以指定 完整 key ?或 key 前綴 來獲取配置信息,下面將基于 /namespance1/ 這個前綴進行獲取并監聽變更來演示效果。
etcd-manage
獲取 etcd 配置數據源
定義接口 IConfigrationWatcher,含 FireChange 方法,這里定義的比較簡單,只在配置發生變更時發出一個信號,所以是 void 類型,但如果要實現對特定 key 變更進行增量處理也是可以的。
public interface IConfigrationWatcher {void FireChange(); }定義接口 IConfigrationRepository,包含 GetConfig 和 Watch 兩個方法。
GetConfig 實現根據指定的前綴從 ectd 獲取配置,轉換成 IDictionary<string, string> 返回。
Watch 則監聽配置變更,當發生變更時,調用 IConfigrationWatcher 對象的 FireChange 方法。
完整實現代碼:EtcdConfigurationRepository.cs,主要使用到 dotnet-etcd 中的 GetRange 和 WatchRange,WatchRange 的實現是基于 gRPC 的雙向流模式,變更通知可以理解為是實時的。
實現 EtcdConfigurationProvider
EtcdConfigurationProvider 的實現和之前的介紹類似,區別在于這里將使用到父類 ConfigurationProvider 的 GetReloadToken 和 OnReload 方法,構造函數中通過 ChangeToken.OnChange 對 ReloadToken 進行狀態變更監聽。
IConfigrationWatcher 的 ?FireChange 觸發 OnReload,OnReload 觸發 ChangeToken 的狀態變化,ChangeToken 的狀態變化觸發 Load 方法重新執行,Data 屬性被重新賦值。
注:需不需要 Reload 可通過 reloadOnChange 參數自定義
public class EtcdConfigurationProvider : ConfigurationProvider, IConfigrationWatcher {private readonly IConfigrationRepository _configRepository;public EtcdConfigurationProvider(IConfigrationRepository configRepository, bool reloadOnChange){_configRepository = configRepository;if (reloadOnChange){_configRepository.Watch(this);ChangeToken.OnChange(() => GetReloadToken(),() => Load());}}public override void Load(){Data = _configRepository.GetConfig();}public void FireChange() => OnReload(); }EtcdConfigurationSource 則返回 EtcdConfigurationProvider 對象即可,最后定義 IConfigurationBuilder 擴展方法 AddEtcd 供使用。完整代碼請參考:Etcd.Configuration
測試效果
appsettings.json 增加 etcd 相關配置參數:
"etcd": {"connectionString": "http://localhost:2379","prefixKeys": ["/namespace1/"],"keyMode": 1 // json 格式 : 分隔 }Program.cs 增加 AddEtcd
public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.ConfigureAppConfiguration(builder =>{builder.AddEtcd(builder.Build().GetSection("etcd"), true);});webBuilder.UseStartup<Startup>();});Startup.cs 的 Configuration 對象中 EtcdConfigurationProvider Data 數據如下:
etcd data
基于這樣的數據格式,可以將其注入到 Namespace1Options 實體上,然后在程序中直接使用 Namespace1Options:
public class Namespace1Options {public string Name { get; set; }public string Company { get; set; } }Startup.cs 的 ConfigureServices 方法中添加如下代碼:
services.Configure<Namespace1Options>(Configuration.GetSection("/namespace1/"));使用 Namespace1Options :
public class WeatherForecastController : ControllerBase {private readonly Namespace1Options _options;public WeatherForecastController(IOptionsSnapshot<Namespace1Options> options){_options = options.Value;}[HttpGet]public ActionResult<IEnumerable<string>> Get(){return new string[] { _options.Name, _options.Company };} }etcd 中對 company 值就行修改,在不重啟服務情況下,馬上生效。
result
參考鏈接:
.NET Core 自定義配置源
dotnet-etcd
etcd-manage
Etcd.Configuration
總結
以上是生活随笔為你收集整理的.NET Core etcd 配置源的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微软面向初学者的机器学习课程:3.1-构
- 下一篇: 如何排查 .NET 内存泄漏