《ASP.NET Core 微服务实战》-- 读书笔记(第9章)

第 9 章 微服务系统的配置

微服务系统中的配置需要关注更多其他方面的因素,包括:

  • 配置值的安全读写

  • 值变更的审计能力

  • 配置信息源本身的韧性和可靠性

  • 少量的环境变量难以承载大型、复杂的配置信息

  • 应用要决定是否支持配置值的在线更新和实时变更,还要决定如何实现

  • 对功能开关和层级化设置的支持

  • 对敏感信息以及加密密钥本身进行存储和读取支持

本章首先讨论在应用中使用环境变量的机制,并演示 Docker 的支持情况

接着探索一个来自 Netflix OSS 技术栈的配置服务器产品

最后将运用 etcd,它是一个常用于配置管理的开源分布式键值数据库

在 Docker 中使用环境变量

为配置提供默认值时,还应该考虑哪些设置在应用启动期间需要通过环境变量进行覆盖

为配置设置值时,可使用键值对显示指定,如下所示:

$ sudo docker run -e SOME_VAR='foo' \ -e PASSWORD='foo' \
-e USER='bar' \
-e DB_NAME='mydb' \
-p 3000:3000 \
--name container_name microservices-aspnetcore/image:tag

或者,如果不希望在命令行中显示传入值,也可以把来自启动环境的环境变量转发到容器内部,只要不传入包含值的等式即可,例如:

$ docker run -e PORT -e CLIENTSCRET -e CLIENTKEY [...]

这一命令将把命令行所在终端中的 PORT、CLIENTSECRET 和 CLIENTKEY 环境变量的值传入 Docker 容器中,在这个过程中它们的值不会在命令行文本中公开,以防范潜在的安全漏洞和敏感信息泄露

如果需要向容器传入大量的环境变量,可以向 docker 命令指定一个包含键值对列表的文件:

$ docker run --env-file ./myenv.file [...]

使用 Spring Cloud 配置服务器

围绕服务的配置管理的最大难题之一,并非如何将值注入到环境变量,而在于这些值本身的日常维护

当配置的原始源处的值发生变更时,我们如何得到通知

更进一步,当值发生变更时,我们如何回溯并查看之前的值

你可能发现,这似乎可用使用类似于 Git 仓库的方法来管理配置值

Spring Cloud 配置服务器(SCCS)的开发人员也持相同看法

要在 .NET Core 应用中添加 SCCS 客户端的支持,只需要在项目中添加对 Steeltoe.Extensions.Configuration.ConfigServer NuGet 包的引用

接着,我们需要配置应用,让它从正确的位置获取设置信息

我们需要定义一个 Spring 应用名称,并在 appsettings.json 文件中添加配置服务器的 URL

{"spring": {"application": {"name": "foo"},"cloud": {"config": {"uri": "http://localhost:8888"}}},"Logging": {"IncludeScopes": false,"LogLevel": {"Default": "Debug","System": "Information","Microsoft": "Information"}}
}

配置完成后,Startup 构造方法仍然与其他应用几乎一致

public Startup(IHostingEnvironment env)
{var builder = new ConfigurationBuilder().SetBasePath(env.ContentRootPath).AddJsonFile("appsettings.json", optional: true, reloadOnChange: false).AddEnvironmentVariables().AddConfigServer(env);Configuration = builder.Build();
}

要添加对配置服务器的支持,接下来需要修改 ConfigureServices 方法

首先调用 AddConfigServer 向依赖注入子系统加入配置客户端

接着指定泛型参数并调用 Configure 方法

这一操作能把从配置服务器获取的配置信息包装为一个 IOptionsSnapshot 对象,然后可由控制器和其他代码使用

public void ConfigureServices(IServiceCollection services)
{services.AddConfigServer(Configuration);services.AddMvc();services.Configure<ConfigServerData>(Configuration);
}

此处,用于表示从配置服务器获取的数据的数据模型,是基于 Spring Cloud 服务器示例仓库中的示例配置进行建模的

public class ConfigServerData
{public string Bar { get; set; }public string Foo { get; set; }public Info Info { get; set; }
}public class Info
{public string Description { get; set; }public string Url { get; set; }
}

然后,在需要时,就可注入这个类的实例,以及配置服务器的客户端参数

public class MyController : MyController
{private IOptionsSnapshot<ConfigServerData> MyConfiguration { get; set; }private ConfigServerClientSettingsOptions ConfigServerClientSettingsOptions { get; set; }public MyController(IOptionsSnapShot<ConfigServerData> opts, IOptions<ConfigServerClientSettingsOptions> clientOpts){...}...
}

上述配备完成后,如果配置服务器已处于运行状态,构造器中的 opts 变量将包含应用所有的相关配置

启动配置服务器最简单的方法就是直接通过 Docker 镜像运行以下代码

$ docker run -p 8888:8888 \
-e SPRING_CLOUD_CONFIG_SERVER_GET_URI=http://github.com/spring-cloud-samples/ \config-repohyness/spring-cloud-config-server

如果服务器运行正确,应该能通过以下命令获取配置信息

curl http://localhost:8888/foo/development

在本地用 Docker 镜像启动配置服务器后,使用上面展示的 C# 代码,就能体验将外部配置数据提供给 .NET Core 微服务的过程

使用 etcd 配置微服务

Spring Cloud 配置服务器的替代品不计其数,etcd 是其中很流行的一个

上一章简单提到,etcd 是一个轻量级的分布式键值数据库

它就是为你存储分布式系统所需要的最关键信息的位置

etcd 是一个集群产品,其节点之间的通信是基于 Raft 共识算法实现的

etcd 的一个最常见运用场景就是存储和检索配置信息以及功能标志

在本章的例子里,我访问 compose.io 并注册了一个免费试用的托管 etcd

创建 etcd 配置提供程序

GitHub链接:https://github.com/microservices-aspnetcore/etcd-client

创建配置源

using System;
using Microsoft.Extensions.Configuration;namespace ConfigClient
{public class EtcdConfigurationSource : IConfigurationSource{public EtcdConnectionOptions Options { get; set; }public EtcdConfigurationSource(EtcdConnectionOptions options){this.Options = options;}public IConfigurationProvider Build(IConfigurationBuilder builder){return new EtcdConfigurationProvider(this);}}
}

创建配置构建器

using System;
using System.Collections.Generic;
using EtcdNet;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;namespace ConfigClient
{public class EtcdConfigurationProvider : ConfigurationProvider{private EtcdConfigurationSource source;public EtcdConfigurationProvider(EtcdConfigurationSource source){this.source = source;}public override void Load(){EtcdClientOpitions options = new EtcdClientOpitions(){Urls = source.Options.Urls,Username = source.Options.Username,Password = source.Options.Password,UseProxy = false,IgnoreCertificateError = true};EtcdClient etcdClient = new EtcdClient(options);try{EtcdResponse resp = etcdClient.GetNodeAsync(source.Options.RootKey,recursive: true, sorted: true).Result;if (resp.Node.Nodes != null){foreach (var node in resp.Node.Nodes){// child nodeData[node.Key] = node.Value;}}}catch (EtcdCommonException.KeyNotFound){// key does notConsole.WriteLine("key not found exception");}}}
}

借助如下扩展方法

using Microsoft.Extensions.Configuration;namespace ConfigClient
{public static class EtcdStaticExtensions{public static IConfigurationBuilder AddEtcdConfiguration(this IConfigurationBuilder builder,EtcdConnectionOptions connectionOptions){return builder.Add(new EtcdConfigurationSource(connectionOptions));}}public class EtcdConnectionOptions{public string[] Urls { get; set; }public string Username { get; set; }public string Password { get; set; }public string RootKey { get; set; }}
}

便能在 Startup 类中把 etcd 添加为配置源

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;namespace ConfigClient
{public class Startup{public Startup(IHostingEnvironment env){var builder = new ConfigurationBuilder().SetBasePath(env.ContentRootPath).AddJsonFile("appsettings.json", optional: false, reloadOnChange: true).AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true).AddEtcdConfiguration(new EtcdConnectionOptions{Urls = new string[] {"https://portal1934-21.euphoric-etcd-31.capital-one-3.composedb.com:17174","https://portal2016-22.euphoric-etcd-31.capital-one-3.composedb.com:17174"},Username = "root",Password = "changeme",RootKey = "/myapp"}).AddEnvironmentVariables();Configuration = builder.Build();}public static IConfigurationRoot Configuration { get; set; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){// Add framework services.services.AddMvc();}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory){loggerFactory.AddConsole();loggerFactory.AddDebug();app.UseMvc();}}
}

使用来自 etcd 的配置值

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using EtcdNet;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;namespace ConfigClient.Controllers
{[Route("api/[controller]")]public class ValuesController : Controller{private ILogger logger;public ValuesController(ILogger<ValuesController> logger){this.logger = logger;}// GET api/values[HttpGet]public IEnumerable<string> Get(){List<string> values = new List<string>();values.Add(Startup.Configuration.GetSection("/myapp/hello").Value);values.Add(Startup.Configuration.GetSection("/myapp/rate").Value);return values;}// GET api/values/5[HttpGet("{id}")]public string Get(int id){return "value";}// POST api/values[HttpPost]public void Post([FromBody]string value){}// PUT api/values/5[HttpPut("{id}")]public void Put(int id, [FromBody]string value){}// DELETE api/values/5[HttpDelete("{id}")]public void Delete(int id){}}
}

现在访问 http://localhost:3000/api/values 端点,将返回这些值:

{"world", "12.5"}

这些正是本节前面面向 etcd 服务器添加的值

只使用了少数几行代码,我们便创建了一个由远程配置服务器支持的、稳定而符合标准的 ASP.NET 配置源

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311914.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构---简单插入排序

数据结构—简单插入排序 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> void simpleInsertSort(int a[], int length) {//简单插入排序int j;for (int i 2; i < length; i) {//从第二个元素开始比较插入if (a[i]…

[蓝桥杯2018初赛]小朋友崇拜圈

题目描述 班里N个小朋友&#xff0c;每个人都有自己最崇拜的一个小朋友&#xff08;也可以是自己&#xff09;。 在一个游戏中&#xff0c;需要小朋友坐一个圈&#xff0c; 每个小朋友都有自己最崇拜的小朋友在他的右手边。 求满足条件的圈最大多少人&#xff1f; 小朋友编号为…

前端 JS/TS 调用 ASP.NET Core gRPC-Web

前言在上两篇文章中&#xff0c;介绍了ASP.NET Core 中的 gRPC-Web 实现 和 在 Blazor WebAssembly 中使用 gRPC-Web&#xff0c;实现了 Blazor WebAssembly 调用 ASP.NET Core gRPC-Web。虽然 ASP.NET Core 中的 gRPC-Web 实现目前还是试验性项目&#xff0c;但是鉴于它在生态…

数据结构---哈夫曼树

数据结构—哈夫曼树 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> #define N 100 #define INF 2^31-1 typedef struct fNode {//哈夫曼树中每个节点的信息int c;//字符int parent;//父节点&#xff0c;左右孩子&am…

热电偶校验仪_热电偶校验方法_烟台一等热电偶,干湿两用温度校验炉公司

杭州中创为您详细解读hzzc6烟台一等热电偶的相关知识与详情&#xff0c;防爆涡轮流量计的转速通过拆正在机壳外的传感线圈来检测&#xff0e;当涡轮流量计叶片切割由壳体内**磁钢发生的磁力线时&#xff0c;就会引起传感线圈中的磁通变革&#xff0e;传感线圈将检测到的磁通周期…

手把手教你用C#做疫情传播仿真

手把手教你用C#做疫情传播仿真在上篇文章中&#xff0c;我介绍了用 C#做的疫情传播仿真程序的使用和配置&#xff0c;演示了其运行效果&#xff0c;但没有着重讲其中的代码。今天我将抽丝剥茧&#xff0c;手把手分析程序的架构&#xff0c;以及妙趣横生的细节。首先来回顾一下运…

word List 10

word List 10 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

java程序员选择多个offer时需要看重哪些?_对不起,我们公司不要本科以下的大学生,学历对于程序员重不重要...

来自普通大学的学生&#xff0c;总会觉得逆袭如梦似幻&#xff0c;机会在哪里&#xff1f;但放长远来看&#xff0c;更重要的是要看到&#xff1a;环境只能影响&#xff0c;却不能决定我们的人生。人生路漫长&#xff0c;最终会怎样&#xff0c;还不一定呢&#xff01;在某综艺…

中小企业团队敏捷产品开发流程最佳实践

近期因为疫情的影响&#xff0c;不少互联网公司开始尝试远程工作。也出不了少如何做好远程工作的方法&#xff0c;我认为不管是场地办公还是远程办公都依赖于原来的产品开发流程。我曾经遵循CMMI5的流程管理过15人左右的跨国/语言/文化团队&#xff0c;也遵循敏捷Scrum管理过9人…

数据结构---二叉线索树

数据结构—二叉线索树 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> typedef struct bmTree {int data;struct bmTree* lchild, *rchild;int ltag, rtag; }bmTree; bmTree * preNULL;//中序遍历的前驱指针 void cr…

revit如何根据坐标进行画线_铭成教你如何根据同步带的齿形进行选型

1、同步带齿形分类梯型齿同步带分为&#xff1a;最轻型MXL、超轻型XXL、特轻型XL、轻型L、重型H、特重型XH、超重型XXH&#xff0c;共七种&#xff0c;这几种是目前市场用的最广泛的。特殊齿型的同步带又分为&#xff1a;最轻型T2.5、轻型T5、重型T10、最重型T20&#xff0c;现…

在VS Code里逛知乎、发文章?知乎 on VS Code来啦!重新定义内容创作!

本文为 牛岱 的原创文章在2020年2月10日首发于“玩转VS Code”知乎专栏你是否已经厌倦了知乎 Web 端文本编辑器糟糕的使用体验和时而出现的奇怪 Bug&#xff1f;身为程序员的你是否想用你最熟悉的 Markdown 语法写答案&#xff0c;并且获得最佳的代码块语法高亮&#xff1f;攥写…

线性代数---向量问题的求解方法

线性代数—向量问题的求解方法 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

java 定时_Java线上定时任务不定期挂掉问题分析

作者&#xff1a;IKNOW本尊问题背景收到频繁的告警邮件&#xff0c;定时任务调度失败&#xff0c;查看xxl-job的执行器列表是空的&#xff0c;但是服务又显示健康&#xff0c;查看历史任务执行记录发现执行器是依次递减&#xff0c;由于是线上服务&#xff0c;只能先重启&#…

gRPC in ASP.NET Core 3.x -- Protocol Buffer, Go语言的例子(上)

前两篇文章半年前写的&#xff1a;gRPC in ASP.NET Core 3.0 -- Protocol Buffer&#xff08;1&#xff09;&#xff0c;gRPC in ASP.NET Core 3.0 -- Protocol Buffer&#xff08;2&#xff09;之前把protocol buffer的基础知识讲了一遍&#xff0c;今天使用Go语言做一些例子。…

word List 11

word List 11 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

温故知新 .Net重定向深度分析

在早期的.NET Framework程序员心里&#xff0c;重定向Redirect其实分为两种&#xff1a;Response.Redirect&#xff1a;Response对象的Redirect方法提供了一种实现客户端重定向的方法Server.Transfer&#xff1a;Server对象的Transfer方法使用服务器执行重定向&#xff0c;并避…

笔记本电脑销量排名_网友总结京东笔记本销量,联想高居第一,华为表现很出色...

笔记本电脑&#xff0c;还是要看大品牌。网友总结近30天京东笔记本销量&#xff0c;结局让人出乎意料。网友直呼&#xff0c;原来华为笔记本这么强。智能手机的出现&#xff0c;对传统的PC行业造成了一定的影响&#xff0c;但它始终还是无法替代PC的功能。在这个行业中&#xf…

数据结构---二叉排序树

数据结构—二叉排序树 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> typedef struct bstTree {int data;struct bstTree* lchild, *rchild; }bstTree; void createBSTTree(bstTree* & T,int data) {//创建二叉…

研发协同平台持续集成2.0架构演进

在上篇《研发协同平台持续集成实践》一文中我们分享了为什么要做持续集成&#xff0c;技术选型&#xff0c;工作原理以及实践落地。今天我们从架构上来分享一下架构层面的设计和演进。持续集成1.0在最开始设计的过程中&#xff0c;本着一切从需求出发&#xff0c;一切以实现业务…