ASP.NET Core 实现微服务 - Consul 配置中心
这一次我们继续介绍微服务相关组件配置中心的使用方法。本来打算介绍下携程开源的重型配置中心框架 apollo 但是体系实在是太过于庞大,还是让我爱不起来。因为前面我们已经介绍了使用Consul 做为服务注册发现的组件
,那么干脆继续使用 Consul 来作为配置中心吧。Consul 除了服务注册发现功能,还有个 Key/Value 存储的功能,我们把本地的 appsettings.json 文件的内容搬到 Key/Value 上就可以实现配置中心了。
把服务的配置迁移至 Consul
让我们来改造一下前面系列文章里的 member_center 项目,把配置文件都迁移到 consul 上面去。
在 consul 控制台点击 “Key/Value” 菜单,点击 “create” 按钮新建一个 Key/Value 对象。
Key/Value 支持按文件夹分类,当我们的 Key 以 / 结尾的时候,consul 会认为这是一个文件夹。
我们在这里输入 “member_center/” 在创建文件夹。
在创建的文件夹目录下继续点击 “create” 按钮。
在 key 文本框里输入 “confing.json” 。
在 Value 文本框内把原来 appsettings.json 文件的全部内容复制粘贴进去。
{"consul_server": "http://192.168.18.164:8500"
}
把原来 appsettings.json 文件的内容全部删除,只输入一行 consul_server 的配置,用来指示 consul 服务的地址。
Install-Package Winton.Extensions.Configuration.Consul
在 member_center 项目上通过nuget安装 Winton.Extensions.Configuration.Consul 这个组件。
public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.ConfigureAppConfiguration((ctx,cfg)=> {var localconfig = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").AddEnvironmentVariables().Build();var consul_server = localconfig["consul_server"];cfg.AddConsul("member_center/config.json",op=> {op.ConsulConfigurationOptions = cco =>{cco.Address = new Uri(consul_server);};op.ReloadOnChange = true;});});webBuilder.ConfigureKestrel(options =>{options.ListenAnyIP(6002);});webBuilder.UseStartup<Startup>();});
在 program 文件的 CreateHostBuilder 方法内配置使用 Consul 做为配置的提供源。首先从本地读取 consul_server 的地址。通过 AddConsul 方法指示需要从 consul 读取的配置文件的路径。完成以上操作后我们的服务已经可以读取到 Consul 存储的配置了。
[ApiController][Route("[controller]")]public class ConsulController : ControllerBase{IConfiguration _configuration;public ConsulController(IConfiguration configuration){_configuration = configuration;}[HttpGet("getConfig")]public string GetConfig(string key){return _configuration[key];}}
我们新建一个GetConfig方法来演示下能否读取到配置。
直接在 Controller 构造函数注入 IConfiguration 来读取配置,这跟我们普通本地配置的读取方式完全一致。
http://localhost:6002/consul/getconfig?key=hotreload_test
在浏览器上访问一下这个action对应的url,并且指定一个key=hotreload_test,可以看到输出的结果跟我们在 consul 上配置的值是一致的。
修改一下 consul 上面的配置值,重新读取一下这个配置,可以看到新的值已经被读取到了,证明我们的热更新也可以运行了。
把 Ocelot 网关的配置迁移至 Consul
上面我们演示了如何把普通服务的配置迁移至 consul,下面演示下如何把 Ocelot 的配置迁移到 Consul 上。
Ocelot 网站其实也就是一个 webapi 项目,本质上跟上面的服务没啥区别。我们根据上面的演示,其实可以很容易的把 Ocelot 项目的配置迁移到 Consul 上。那么为什么需要单独说一下 Ocelot 网关的迁移呢?
本来 Ocelot 的路由配置需要把下游服务的地址跟端口在配置文件里写死,那样的话,我们的 Consul 服务注册发现就没有意义了,我们的下游服务都是可能动态变化的。所以我们需要让 Ocelot 结合 Consul 的服务注册发现功能来把下游服务器的配置动态化。这就导致 Ocelot 项目跟 Consul 的融合会比一般的服务复杂一点。
Install-Package Ocelot.Provider.Consul
首先我们在项目上使用 nuget 安装 Ocelot.Provider.Consul 这个组件。
{"consul_server": "http://192.168.18.164:8500"
}
同样我们需要在本地的 appsettings.json 文件内指定 consul_server 的地址。再把 routes.json 文件的内容全部迁移至 consul 的 key/value 上去,这个不在赘述。
注意,这里不是简单的复制粘贴 routes.json 文件的内容。
我们需要把原来的 DownstreamHostAndPorts 配置全部删掉,替换成服务名,并且指定负载均衡的算法。
"ServierName" : "hotel_base",
"LoadBalanceOptions": {"Type": "LeastConnection"
}
在 "GlobalConfiguration" 节点指定 "ServiceDiscoveryProvider":
"ServiceDiscoveryProvider": {"Scheme": "http","Host": "192.168.18.164","Prot": 8500,"Type": "Consul"
}
ServiceDiscoveryProvider 节点指示了使用 Consul 做为服务发现的组件及Consul服务的基本信息。
public static void Main(string[] args){new WebHostBuilder().UseKestrel().UseContentRoot(Directory.GetCurrentDirectory()).ConfigureAppConfiguration((hostingContext, config) =>{var localconfig = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").AddEnvironmentVariables().Build();var consul_server = localconfig["consul_server"];config.AddConsul("gateway/routes.json", op => {op.ConsulConfigurationOptions = cco =>{cco.Address = new Uri(consul_server);};op.ReloadOnChange = true;});config.AddEnvironmentVariables();}).ConfigureServices(s => {s.AddOcelot().AddConsul().AddTransientDefinedAggregator<HotelDetailInfoForMobileAggregator>();}).ConfigureLogging((hostingContext, logging) =>{logging.AddConsole();}).UseIISIntegration().Configure(app =>{app.UseOcelot().Wait();}).Build().Run();}
我们改造一下 program 文件的 main 方法,在ConfigureAppConfiguration的配置方法内首先获取 consul_server 的地址。通过AddConsul方法指示获取配置文件的地址。
以上跟服务的配置迁移都是一致的,除了以上操作使用 Consul 作为 ServiceDiscoveryProvider 还需要在 ConfigureServices 方法的配置函数内指定 consul 相关的依赖注入。
s.AddOcelot().AddConsul()
我们运行起来所有的服务跟网关项目,访问一下 /api/hotel 这个路由,可以看到请求被正确的转发到了对应的服务上了。
总结
以上我们演示了如何把服务的配置迁移到 Consul 的 Key/Value 对象上并且实现了配置的读取及热更新。演示了 Ocelot 网关的路由配置如何迁移到 Consul 的 Key/Value 对象上并且不再写死下游服务的配置信息,而是使用 Consul 的服务发现能力动态获取下游服务的配置信息。通过以上演示我们可以发现整个过程还是非常简单易用的,虽然 Consul 做为配置中心功能相对于 apollo 等功能还不够强大,比如没有版本管理,用户权限,审计等功能,但是对于一些小的微服务项目也已经足够了。如果你的微服务体系中使用了 Consul 做为服务注册发现的组件,那么可以直接使用 Consul 来做为配置中心,这样在能够获得基本的配置中心能力同时也省去了再部署一套单独的配置中心的繁琐操作。
相关文章:

ASP.NET Core 实现微服务 - Consul 配置中心
这一次我们继续介绍微服务相关组件配置中心的使用方法。本来打算介绍下携程开源的重型配置中心框架 apollo 但是体系实在是太过于庞大,还是让我爱不起来。因为前面我们已经介绍了使用Consul 做为服务注册发现的组件 ,那么干脆继续使用 Consul 来作为配置…...

使用redis的5种常用场景
文章目录 1. 缓存热点数据2. 分布式锁3. 计数器和限流器4. 消息队列5. 会话管理总结 在日常开发工作中,Redis作为一款高性能的内存数据库,凭借其强大的功能特性和卓越的性能表现,已经成为了许多项目中不可或缺的组件。本文将详细介绍Redis在实…...

微信小程序防止重复点击事件
直接写在app.wpy里面,全局可以调用 // 防止重复点击事件preventActive(fn) {const self this;if (this.globalData.PageActive) {this.globalData.PageActive false;if (fn) fn();setTimeout(() > {self.globalData.PageActive true;}, 3000); //设置该时间内…...

PySpark用sort-merge join解决数据倾斜的完整案例
假设有两个大表 table1 和 table2 ,并通过 sort-merge join 来解决可能的数据倾斜问题。 from pyspark.sql import SparkSession from pyspark.sql.functions import col# 初始化SparkSession spark SparkSession.builder.appName("SortMergeJoinExample&quo…...

sklearn-逻辑回归-制作评分卡
目录 数据集处理 分箱 分多少个箱子合适 分箱要达成什么样的效果 对一个特征进行分箱的步骤 分箱的实现 封装计算 WOE 值和 IV值函数 画IV曲线,判断最佳分箱数量 结论 pd.qcut 执行报错 功能函数封装 判断分箱个数 在银行借贷场景中,评分卡是…...

scrapy爬取图片
scrapy 爬取图片 环境准备 python3.10scrapy pillowpycharm 简要介绍scrapy Scrapy 是一个开源的 Python 爬虫框架,专为爬取网页数据和进行 Web 抓取而设计。它的主要特点包括: 高效的抓取性能:Scrapy 采用了异步机制,能够高效…...

在 Vue 项目中使用地区级联选
在 Vue 项目中使用地区级联选择的完整流程: 1.安装依赖包,这个包提供了中国省市区的完整数据。 npm install element-china-area-data --save 2.导入数据 import { regionData } from element-china-area-data 这个包提供了几种不同的数据格式&#…...

【简博士统计学习方法】第1章:1. 统计学习的定义与分类
自用笔记 1. 统计学习的定义与分类 1.1 统计学习的概念 统计学习(Statistical Machine Learning)是关于计算机基于数据构建概率统计模型并运用模型对数据进行预测与分析的一门学科。 以计算机和网络为平台;以数据为研究对象;以…...

利用 Python 脚本批量创建空白 Markdown 笔记
文章目录 利用 Python 脚本批量创建空白 Markdown 笔记1 背景介绍2 需求描述3 明确思路4 具体实现4.1. 遍历 toc.md 文件,收集文件名和对应的文件内容4.2. 实现文件批量生成逻辑4.3. 补全缺失的工具函数4.4. 进一步补全工具函数中的工具函数 5 脚本运行6 注意事项 利…...

【Qt】C++11 Lambda表达式
1. 举例 connect(ui->pushButton, &QPushButton::clicked, [](bool checked){//具体代码qDebug() << "Hello" << checked;}); 2. 详情 //完整形式 [ capture ] ( params ) opt -> ret { body; }; capture 是捕获列表params 是参数表opt 是函数…...

怎样提高服务器中的数据传输速度?
服务器中的数据传输速度会影响着用户的体验感,当企业中的数据传输速度出现卡顿或者是过慢时,用户不能及时浏览到所需的内容,给用户造成不好的体验感,那么企业该怎样才能提高服务器中的数据传输速度呢? 服务器之间如何传…...

Vue 封装公告滚动
文章目录 需求分析1. 创建公告组件Notice.vue2. 注册全局组件3. 使用 需求 系统中需要有一个公告展示,且这个公告位于页面上方,每个页面都要看到 分析 1. 创建公告组件Notice.vue 第一种 在你的项目的合适组件目录下(比如components目录&a…...

JVM实战—12.OOM的定位和解决
大纲 1.如何对系统的OOM异常进行监控和报警 2.如何在JVM内存溢出时自动dump内存快照 3.Metaspace区域内存溢出时应如何解决(OutOfMemoryError: Metaspace) 4.JVM栈内存溢出时应如何解决(StackOverflowError) 5.JVM堆内存溢出时应该如何解决(OutOfMemoryError: Java heap s…...

【python翻译软件V1.0】
如果不想使用密钥的形式,且需要一个直接可用的中英文翻译功能,可以使用一些免费的公共 API,如 opencc 或其他无需密钥的库,或直接用 requests 获取翻译结果。 其中,我可以给你一个简单的代码示例,使用 tra…...

Spring Boot中的依赖注入是如何工作
Spring Boot 中的依赖注入(Dependency Injection,简称 DI)是通过 Spring 框架的核心机制——控制反转(Inversion of Control,IOC)容器来实现的。Spring Boot 基于 Spring Framework,在应用中自动…...

ubuntu22.04 编译安装libvirt 10.x
环境安装 sudo apt-get update -y sudo apt-get install qemu-system-x86 bridge-utils libyajl-dev -y sudo apt-get install build-essential autoconf automake libtool -y sudo apt-get install libxml2-dev libxslt1-dev libgnutls28-dev libpciaccess-dev libnl-3-de…...

[fastadmin] 第三十四篇 FastAdmin 商城模块标签使用详解
FastAdmin 商城模块标签使用详解 一、标签基本语法 1.1 基础语法格式 {shop:goodslist flag"参数值" id"变量名" row"数量"}<!-- 循环内容 --> {/shop:goodslist}1.2 常用参数说明 flag: 商品标记筛选id: 循环变量名row: 显示数量 1.…...

(2024,LLaVA-Bench (Wilder),LLaVA-NeXT,LLaMA3,Qwen-1.5,语言模型扩展)
LLaVA-NeXT: Stronger LLMs Supercharge Multimodal Capabilities in the Wild 目录 1. 简介 2. 探索大规模语言模型的能力极限 3. LLaVA-Bench (Wilder):日常生活视觉聊天基准 4. Benchmark 结果 1. 简介 我们通过引入近期更强大的开源大语言模型(…...

IPEX-LLM开发项目过程中的技术总结和心得
IPEX-LLM开发项目过程中的技术总结和心得 在人工智能快速发展的时代,高效地开发和部署大语言模型(LLM)已成为技术人员的必备技能。在我们的项目中,我们采用了 Intel Extension for PyTorch(简称 IPEX)和 L…...

HTTP/HTTPS ②-Cookie || Session || HTTP报头
这里是Themberfue 上篇文章介绍了HTTP报头的首行信息 本篇我们将更进一步讲解HTTP报头键值对的含义~~~ ❤️❤️❤️❤️ 报头Header ✨再上一篇的学习中,我们了解了HTTP的报头主要是通过键值对的结构存储和表达信息的;我们已经了解了首行的HTTP方法和UR…...

【软考】软件设计师
「学习路线」(推荐该顺序学习,按照先易后难排序) 1、上午题—计算机系统(5~6分)[1.8; ] 2、上午题—程序设计语言(固定6分)[1.9; ] 3、下午题—试题一(15分) 4、上午题—…...

K8s Pod OOMKilled,监控却显示内存资源并未打满
1. 问题现象 pod一直重启,通过grafana查看,发现内存使用率并没有100%。 2. 排查过程 2.1 describe查看pod最新一次的状态 可以明显看到,最近一次的重启就是因为内存不足导致的。 2.2 describe 查看node节点状态 找到原因了,原来…...

C++ 原子变量
C 原子变量 文章目录 C 原子变量1. 原子变量是什么?2. 原子操作的特点3. 原子变量的作用1. 多线程安全的共享数据访问2. 替代锁机制3. 实现低级同步算法 4. 原子变量的常见操作5. 内存顺序(Memory Ordering)内存顺序控制在原子变量中的作用如…...

linux网络 | http结尾、理解长连接短链接与cookie
前言:本节是http章节的最后一部分,主要解释一些小概念。讲解到了HTTP的方法,表单, 重定向等等。 现在废话不多说, 开始我们的学习吧。 ps:本节内容都是概念, 知道就行, 友友们放心观…...

金融项目实战 02|接口测试分析、设计以及实现
目录 ⼀、接口相关理论 二、接口测试 1、待测接口:投资业务 2、接口测试流程 3、设计用例理论 1️⃣设计方法 2️⃣工具 4、测试点提取 5、测试用例 ⼀、接口相关理论 1、ui功能测试和接⼝测试那个先执⾏?为什么? 结论:…...

二、智能体强化学习——深度强化学习核心算法
2.1 DQN 系列及其改进 2.1.1 背景与动机 在经典强化学习中(如 Q-Learning),如果状态空间或动作空间非常大乃至连续,那么用一个表格来存储 Q ( s , a ) Q(s,a) Q(s,a) 不再可行。为了解决该问题,可以使用神经网络来逼…...

Mysql--架构篇--存储引擎InnoDB(内存结构,磁盘结构,存储结构,日志管理,锁机制,事务并发控制等)
MySQL是一个多存储引擎的数据库管理系统,支持多种不同的存储引擎。每种存储引擎都有其独特的特性、优势和适用场景。选择合适的存储引擎对于优化数据库性能、确保数据完整性和满足业务需求至关重要。 注:在同一个Mysql的数据库中,对于不同的表…...

JVM实战—13.OOM的生产案例
大纲 1.每秒仅上百请求的系统为何会OOM(RPC超时时间设置过长导致QPS翻几倍) 2.Jetty服务器的NIO机制如何导致堆外内存溢出(S区太小 禁NIO的显式GC) 3.一次微服务架构下的RPC调用引发的OOM故障排查实践(MAT案例) 4.一次没有WHERE条件的SQL语句引发的OOM问题排查实践(使用MA…...

client-go 的 QPS 和 Burst 限速
1. 什么是 QPS 和 Burst ? 在 kubernetes client-go 中,QPS 和 Burst 是用于控制客户端与 Kubernetes API 交互速率的两个关键参数: QPS (Queries Per Second) 定义:表示每秒允许发送的请求数量,即限速器的平滑速率…...

使用docker-compose安装Redis的主从+哨兵模式
必看 本文是一主二从一哨兵模式;其余的单机/集群/多哨兵模式的话,不在本文... 本文的环境主要是:应用app在本地,redis在云服务器上; 图解 图如下:这个图很重要; 之所以要这样画图࿰…...