.net core 微服务之 Consul配置中心
概念
什么是配置中心
配置是用来动态修改程序执行的一种行为的机制,实现热更新
为什么要使用配置中心
安全性:配置跟随源代码保存在代码库中,容易造成配置泄漏。
时效性:修改配置,需要重启服务才能生效。
局限性:无法支持动态调整:例如日志开关、功能开关。
因此,分布式配置中心应运而生!
现阶段主流的配置中心类型
Apollo,java开发 ----- 运维成本比高 Apollo分为MySQL,Config Service,Admin Service,Portal四个模块,MySQL存储Apollo元数据和用户配置数据; Config Service提供配置的读取、推送等功能,客户端请求都是落到Config Service上; Admin Service提供配置的修改、发布等功能,Portal操作的服务就是Admin Service; Portal提供给用户配置管理界面;功能强大,社区活跃,但较为复杂,部署组件较多,运维成本比高 Consul, go开发 依赖:不依赖其他组件 应用内/外:属于外部应用,侵入性小 ACP原则:遵循CP原则(一致性+分离容忍) 服务注册稍慢,由于其一致性导致了在Leader挂掉时重新选举期间真个consul不可用。 版本迭代:目前仍然进行版本迭代 集成支持:支持SpringCloud K8S集成 访问协议:HTTP/DNS 雪崩保护:不支持雪崩保护 集成:SpringCloud集成,K8S集成 自动注销实例:不支持 界面:英文界面,不符合国人习惯 上手:复杂一点 Nacos,依赖:mysql ----- 依赖:mysql 应用内/外:属于外部应用,侵入性小 ACP原则:通知遵循CP原则(一致性+分离容忍) 和AP原则(可用性+分离容忍) 版本迭代:目前仍然进行版本迭代,最近的提交是几天前 集成支持:支持Dubbo 、SpringCloud、K8S集成 访问协议:HTTP/动态DNS/UDP 雪崩保护:支持雪崩保护 Spring cloud config java开发 ----- Net支持比较差 自动注销实例:支持 界面:国产服务,中文界面,符合国人习惯 上手:极易,中文文档,案例,社区活跃 Consul实际上是和Nacos比较相似的产品,虽然Consul目前的主要发展方向放在了Service Mesh,但是Consul最初支持的服务发现和配置管理,也是Nacos的两大功能。虽然Nacos在Consul之后以与之相似的部署架构开源,但这并不意味着Nacos在功能和架构上也模仿Consul,Nacos的架构和功能是由阿里巴巴内部十年的运行演进经验得来,所以二者的比较也一定会让大家更加了解他们的定位和演进方向是完全不一样的。
Consul 配置中心示例
单服务单个配置文件
1. Nuget引入包
Winton.Extensions.Configuration.Consul
2. Program文件中配置
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureAppConfiguration((hostingContext, config) => { // 加载默认配置信息到Configuration hostingContext.Configuration = config.Build(); // 加载consul配置中心配置 //string consul_url = hostingContext.Configuration["Consul_Url"]; string consul_url = "http://localhost:8500"; config.AddConsul( "appsettings.json", options => { options.ConsulConfigurationOptions = cco => { cco.Address = new Uri(consul_url); }; // 1、consul地址 options.Optional = true; // 2、配置选项 options.ReloadOnChange = true; // 3、配置文件更新后重新加载 options.OnLoadException = exceptionContext => { exceptionContext.Ignore = true; }; // 4、忽略异常 } ); // 5、consul中加载的配置信息加载到Configuration对象,然后通过Configuration 对象加载项目中 hostingContext.Configuration = config.Build(); }); webBuilder.UseStartup<Startup>(); });
3. 在Consul客户端中新增一个key为 appsettings.json 的Json文件,将我们项目中的 appsettings.json 文件内容拷贝进去
4. 在项目中新建一个读取配置的接口,方便测试,读取配置文件中key为 test_name 的值
/// <summary> /// 测试配置中心 /// </summary> /// <returns></returns> [HttpGet("TestConfiguration")] public async Task<IActionResult> TestConfiguration() { return Ok($"当前配置的name是:{_configuration.GetSection("test_name")?.Value}"); }
运行测试一下,
在consul客户端中修改配置文件中的值 ,不用重启项目,再次运行
多服务单个配置文件
这里的key 命名方式就是 : {服务名称}/appsettings.json 。 或者 {服务名称}/appsettings.{环境名称}.json
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureAppConfiguration((hostingContext, config) => { #region 2. 多服务单配置 // 加载默认配置信息到Configuration hostingContext.Configuration = config.Build(); // 加载consul配置中心配置 ////string consul_url = hostingContext.Configuration["Consul_Url"]; string consul_url = "http://localhost:8500"; // 动态加载环境信息,主要在于动态获取服务名称和环境名称 var env = hostingContext.HostingEnvironment; config.AddConsul( // $"{env.ApplicationName}/appsettings.{env.EnvironmentName}.json", $"{env.ApplicationName}/appsettings.json", options => { options.ConsulConfigurationOptions = cco => { cco.Address = new Uri(consul_url); }; // 1、consul地址 options.Optional = true; // 2、配置选项 options.ReloadOnChange = true; // 3、配置文件更新后重新加载 options.OnLoadException = exceptionContext => { exceptionContext.Ignore = true; }; // 4、忽略异常 } ); // 5、consul中加载的配置信息加载到Configuration对象,然后通过Configuration 对象加载项目中 hostingContext.Configuration = config.Build(); #endregion }); webBuilder.UseStartup<Startup>(); });
多服务多个配置文件
每个服务可能还有多个配置文件或者共用的一个配置文件。这里我就在特定的服务里面新加一个自定义的配置文件和一个所有服务共用的配置文件
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureAppConfiguration((hostingContext, config) => { #region 3. 多服务多配置 // 加载默认配置信息到Configuration hostingContext.Configuration = config.Build(); // 加载consul配置中心配置 ////string consul_url = hostingContext.Configuration["Consul_Url"]; string consul_url = "http://localhost:8500"; // 动态加载环境信息,主要在于动态获取服务名称和环境名称 var env = hostingContext.HostingEnvironment; config.AddConsul( // $"{env.ApplicationName}/appsettings.{env.EnvironmentName}.json", $"{env.ApplicationName}/appsettings.json", options => { options.ConsulConfigurationOptions = cco => { cco.Address = new Uri(consul_url); }; // 1、consul地址 options.Optional = true; // 2、配置选项 options.ReloadOnChange = true; // 3、配置文件更新后重新加载 options.OnLoadException = exceptionContext => { exceptionContext.Ignore = true; }; // 4、忽略异常 } ) .AddConsul( $"{env.ApplicationName}/custom.json", options => { options.ConsulConfigurationOptions = cco => { cco.Address = new Uri(consul_url); }; // 1、consul地址 options.Optional = true; // 2、配置选项 options.ReloadOnChange = true; // 3、配置文件更新后重新加载 options.OnLoadException = exceptionContext => { exceptionContext.Ignore = true; }; // 4、忽略异常 } ) .AddConsul( $"common.json", options => { options.ConsulConfigurationOptions = cco => { cco.Address = new Uri(consul_url); }; // 1、consul地址 options.Optional = true; // 2、配置选项 options.ReloadOnChange = true; // 3、配置文件更新后重新加载 options.OnLoadException = exceptionContext => { exceptionContext.Ignore = true; }; // 4、忽略异常 } ) ; // 5、consul中加载的配置信息加载到Configuration对象,然后通过Configuration 对象加载项目中 hostingContext.Configuration = config.Build(); #endregion }); webBuilder.UseStartup<Startup>(); });
在服务接口中添加测试
/// <summary> /// 测试配置中心 /// </summary> /// <returns></returns> [HttpGet("TestConfiguration")] public async Task<IActionResult> TestConfiguration() { // return Ok($"当前配置的name是:{_configuration.GetSection("test_name")?.Value}"); return Ok( @$"服务对应配置:{_configuration.GetSection("test_name")?.Value} 服务对应自定义配置:{ _configuration.GetSection("custom_name")?.Value} 共用配置:{ _configuration.GetSection("common_name")?.Value} " ); }
运行效果