.NetCore快速上手Consul,留给自己一点思考的空间
互联网热潮下,“微服务”技术架构成为了一种高大上的技术,其顾名思义就是将传统的大的业务服务拆分成独立的小服务,当拆分的服务慢慢多起来的时候,我们会发现服务地址很难管理,传统的方式一般会通过配置文件或者数据库存储,这种手动的维护的方式显然不够灵活,如果某个服务挂了,系统得不到及时的通知,只能等维护人员处理。这个时候如果有个中间件来做服务发现的话,显然会显得很灵活。
.Net平台上使用“微服务”时做服务发现,目前来说Cosul是一个不错的选择。
什么是Consul
Consul是一种提供了服务发现,配置管理等功能的服务网格解决方案,是一种分布式,高可用的服务管理架构。
主要功能:
服务发现(Service Discovery):Consul提供了通过DNS或者HTTP API接口的方式来发现服务。服务与服务之间通过Consul中心来统一获取调用服务的地址,而不再是传统模式下服务之间调用的“硬编码”配置管理。
服务注册(Service Register):Consul提供了两种方式进行服务注册。第一种通过Http API的方式在服务启动时注册,第二种通过json配置文件的方式注册。
健康检查(Health Checking):一旦服务注册到Consul的client节点下,consul就会根据服务注册时配置的间隔时间,主动请求服务,以获取服务的健康状态,如发现不健康的服务,则将该服务从consul中注销。
Key/Value存储:应用程序可以根据自己的需要使用Consul提供的Key/Value存储。 Consul提供了简单易用的HTTP接口,结合其他工具可以实现动态配置、功能标记、领袖选举等等功能。
一张图简单了解下Consul

client节点
Client表示consul的client模式,即客户端模式。
1)client节点负责转发请求给server节点,本身不持久化任何信息
2)提供服务健康检查
3)client节点支持任意扩展,数量不受限制。
server 节点
Server表示consul的server模式,即服务端模式。
1)server节点接收client的转发请求,并本地持久化这些信息,遇到故障后方便排查。
2)consul集群中至少有一个server,官方建议server节点的个数3个或者5个比较合适(集群管理)。server的集群解决了单点问题,server间需要选举一个ledger,由server-ledger负责server集群之间的信息同步。
3)采用Raft一致性协议,保证server节点之间数据一致
consul节点间通信
Consul使用GossIP协议管理成员关系、广播消息到整个集群,包括两个gossip pool(LAN pool和WAN pool),LAN pool是同一个数据中心内部通信的,WAN pool是多个数据中心之间通信的,LAN pool有多个,WAN pool只有一个。
通过上图我们会发现,consul推荐是以集群的形式部署。但是很多人刚开始接触学习的时候并没有那么多机器模拟(Docker模拟咱先不讨论了),server单节点模式是否可行呢?
答案当然是可行的,但弊端也显而易见,首先肯定会有单点故障问题,其次如果注册的服务太多,server需要不断的向服务发送请求,进行健康检查,显然大量、高频次的请求会极大影响consul节点。
如果只有一个server节点,那么实际上它自身即充当了client又充当了server。本文我们就以server单节点的模式,以最简单的应用和大家学习一下如何在.netcore中使用consul。
准备环境.netcore3.1 、consul部署包
首先下载consul,官方地址:https://www.consul.io/downloads,解压我们会发现就是一个exe程序,掌握一些常用的cmd命令即可。
本地环境consul启动CMD命令:
首先cd到consul.exe所在目录目录
然后输入consul agent -server -bootstrap-expect=1 -node=service1 -bind=127.0.0.1 -data-dir=./data -client=0.0.0.0 -ui -config-dir=./config
常用参数说明:
-server:表示consul代理模式,有两个选择-server和-client
-bootstrap-expect:在一个数据中心中期望提供的server节点数量,只有等到指定数量的server全部启动后,才会启动集群(自行选举ledger)
-node:集群中节点名称,同一集群中唯一,默认为主机名
-bind:绑定集群内部通信的地址,表示该节点监听的地址,这个地址必须是集群内部所有节点可达的。默认是0.0.0.0(将绑定机器得所有地址,同时把 ipv4地址告诉集群得其他人)
-client:绑定客户端的ip地址,默认127.0.0.1,可绑定多个。0.0.0.0表示谁都可以访问。
-data-dir:用于存放Agent状态的目录
-ui:启用web ui
-config-dir:配置目录,将加载目录中的 .hcl 或 .json 格式配置。 注意子路径不会加载
启动consul后,我们可以通过http://localhost:8500访问consuld的UI页面

HTTP方式注册.netcore服务
新建API项目(服务A)

Nuget添加consul依赖包

添加Consul参数配置
{
"ConsulConfig": {
"ServiceName": "WebApi1",
"ServiceIP": "localhost",
"ServicePort": 6000,
"HealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
}
}
注册服务
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting();
//添加consul服务注册
app.UseConsul(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
consul服务注册具体实现逻辑
public static class ConsulExtensions
{
public static IApplicationBuilder UseConsul(this IApplicationBuilder app)
{
//获取consul配置实例
var consulConfig = app.ApplicationServices.GetRequiredService<IOptions<ConsulOptions>>().Value;
//获取应用程序声明周期事件
var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
var consulClient = new ConsulClient(c =>
{
//consul服务注册地址
c.Address = new Uri(consulConfig.ConsulAddress);
}); //服务注册配置
var registration = new AgentServiceRegistration()
{
ID = Guid.NewGuid().ToString(),
Name = consulConfig.ServiceName,//服务名称
Address = consulConfig.ServiceIP,//服务IP
Port = consulConfig.ServicePort,//服务端口
Check = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动后多久注册服务
Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔
HTTP = $"http://{consulConfig.ServiceIP}:{consulConfig.ServicePort}{consulConfig.HealthCheck}",//健康检查地址
Timeout = TimeSpan.FromSeconds(5)//超时时间
}
}; //服务注册
consulClient.Agent.ServiceRegister(registration).Wait(); //应用程序结束时 取消注册
lifetime.ApplicationStopping.Register(() =>
{
consulClient.Agent.ServiceDeregister(registration.ID).Wait();
}); return app;
}
}
1)使用IOptions管理配置类ConsulOptions,将配置文件(比如appsettings.json)中的配置反序列化至配置类的实例中
2)AgentServiceRegistration代理服务注册类,实例化注册服务配置。
健康检查接口
[Route("[controller]")]
[ApiController]
public class HealthCheckController : ControllerBase
{
/// <summary>
/// 健康检查接口
/// </summary>
/// <returns></returns>
[HttpGet]
public IActionResult Get() => Ok();
}
consul节点会根据配置的间隔时间进行定期请求改健康检查接口,获取服务健康状态。
服务启动
查看consul UI页面我们会发现我们注册的服务WebApi1信息已显示

那么如何做到服务发现呢?
通常情况下,如果服务B调用服务A,需要在服务B中配置并指向服务A的地址,也就是上面说的“硬编码”的配置方式,这种模式下,如果服务A部署了多个,那么就需要管理多个地址,并且服务B本身无法知道某个服务A挂掉就放弃请求。
而consul为我们提供了便利,现在服务B不用关心服务A具体的服务地址以及服务A是否健康。服务B直接请求consul服务地址,告诉它我要访问服务A,consul就会启动服务发现机制,找到所有已注册并且健康的服务A,然后根据选择其中的一个返回给服务B,然后服务B根据服务A具体的地址发起请求。consul帮我们管理了服务地址和服务健康检查。
下面我们就模拟一下consul的服务发现。
服务发现
新建API项目(服务B)

Nuget添加consul依赖包

模拟服务发现
[HttpGet]
[Route("/consul")]
public void ReuestConsul()
{
//获取Consul配置地址
var consulAddress = _configuration["ConsulAddress"]?.ToString();
using (var consulClient = new ConsulClient(x => x.Address = new Uri(consulAddress)))
{
//获取根据服务注册名称webApi1 获取consul注册的服务
var services = consulClient.Catalog.Service("WebApi1").Result.Response;
if (services != null && services.Any())
{
//模拟随机一台进行请求,这里只是测试,可以选择合适的负载均衡框架
Random r = new Random();
int index = r.Next(services.Count());
var service = services.ElementAt(index);
using (HttpClient client = new HttpClient())
{
//请求服务WebApi1
var response = client.GetAsync($"http://{service.ServiceAddress}:{service.ServicePort}/api/values").Result;
string result = response.Content.ReadAsStringAsync().Result;
}
}
}
}
1)ConsulClient实例化consul服务节点
2)consulClient.Catalog.Service("服务名称").Result.Response根据服务名称,获取conusl注册的所有服务地址信息(IP、端口)。
好了,本文主要是采用server单节点的模式,和大家介绍了一下consul的特性,以及结合.netcore做了服务注册和模拟了服务发现。
我相信,大家带着动手测试一遍,也会有所思考和收获。
.NetCore快速上手Consul,留给自己一点思考的空间的更多相关文章
- EF Core 快速上手——EF Core 入门
EF Core 快速上手--EF Core 介绍 本章导航 从本书你能学到什么 对EF6.x 程序员的一些话 EF Core 概述 1.3.1 ORM框架的缺点 第一个EF Core应用 本文是对 ...
- Netron开发快速上手(一):GraphControl,Shape,Connector和Connection
版权所有,引用请注明出处:<<http://www.cnblogs.com/dragon/p/5203663.html >> 本文所用示例下载FlowChart.zip 一个用 ...
- NHibernate3快速上手教程FluentNHibernate配置与DBHelper
很多学习NHibernate的新手很容易卡在配置文件这一关,正所谓万事开头难,上手后再配合官方文档就比较容易了. 网上关于配置文件的资料非常多,但由于版本的问题,许多老的教程中都没有明确指出类库的版本 ...
- 快速上手RaphaelJS-Instant RaphaelJS Starter翻译(一)
(目前发现一些文章被盗用的情况,我们将在每篇文章前面添加原文地址,本文源地址:http://www.cnblogs.com/idealer3d/p/Instant_RaphaelJS_Start ...
- UnityShader快速上手指南(三)
简介 这一篇还是一些基本的shader操作:裁剪.透明和法向量的应用 (纠结了很久写不写这些,因为代码很简单,主要是些概念上的东西) 先来看下大概的效果图:(从左到右依次是裁剪,透明,加了法向量的透明 ...
- knockoutJS 快速上手
翻译:Knockout 快速上手 - 3: knockoutJS 快速上手 许多时候,学会一种技术的有效方式就是使用它解决实际中的问题.在这一节,我们将学习使用 Knockout 来创建一个常见的应用 ...
- socket网络编程快速上手(二)——细节问题(4)
5.慢系统调用及EINTR 还记得前面readn和writen函数么?里面有个EINTR,现在就来谈谈这个,这个很重要. Linux世界有个叫信号的东西,感觉他就像一位隐士,很少遇到他,而他又无处不在 ...
- socket网络编程快速上手(一)
工作以来,写了很多socket相关的代码.磕磕碰碰,走了很多弯路,也积累了一些东西,今天正好整理一下.为了证明不是从书上抄来的,逻辑会有点乱(借口,呵呵)!知识点的介绍也不会像书上说的那么详细和精准, ...
- 聊天系统Demo,增加文件传送功能(附源码)-- ESFramework 4.0 快速上手(14)
本文我们将介绍在ESFramework 4.0 快速上手(08) -- 入门Demo,一个简单的IM系统(附源码)的基础上,增加文件传送的功能.如果不了解如何使用ESFramework提供的文件传送功 ...
随机推荐
- memcached+magent的集群部署详细过程
问题描述 Memcached在实现分布集群部署时, Memcached服务端的之间是没有通讯的,服务端是伪分布式,实现分布式是由客户端实现的,客户端实现了分布式算法把数据保存到不同的Memcached ...
- 【Git】4、创建代码仓库,HTTP、SSH拉取远端代码
拉取远端代码:使用Git命令下载远程仓库到本地 文章目录 拉取远端代码:使用Git命令下载远程仓库到本地 1.创建远程代码仓库 2.创建仓库 3.进入仓库 4.HTTP(S)获取远程仓库 首次拉取 更 ...
- Head First 设计模式 —— 15. 与设计模式相处
模式 是在某情境(context)下,针对某问题的某种解决方案. P579 情景:应用某个模式的情况 问题:你想在某情境下达到的目标,但也可以是某情境下的约束 解决方案:一个通用的设计,用来解决约束. ...
- 【Linux】CentOS7中yumbackend.py进程的结束方法
环境: CentOS Linux release 7.3.1611 (Core) 今天启动这个不怎么用的机器,才启动,就发现后台的yum无法进行安装,持续报这个错误 Loaded plugins: f ...
- kernel升级模式RKS让人振奋
前几天刚将我的ERP内核从701_rel 升级到721_ext_rel,看到721的说明了讲到,对于这次的更新,支持RKS(Rolling Kernel Switch)了,简单的讲,就是以后对于内核的 ...
- 微信小程序 发送模板消息的功能实现
背景 - 小程序开发的过程中,绝大多数会满足微信支付 - 那么,作为友好交互的体现,自然就会考虑到支付后的消息通知咯 - 所以,我的小程序项目也要求完成这个效果,so.分享一下自己的实现步骤,以方便道 ...
- Netty编解码器(理论部分)
背景知识 在了解Netty编解码之前,先回顾一下JAVA的编解码: 编码(Encode):在java中称之为序列化,把内存中易丢失的数据结构或对象状态转换成另一种可存储(存储到磁盘),可在网络间传输的 ...
- jemeter断言和性能分析
一.添加断言 1.原因:检查是否有该结果,一般一个请求过去除了400和500的只要通过的都会代表请求成功,比如登录页面及时填写了错误密码,虽然会返回密码错误,但这个请求还是成功的,所以我们要添加断言, ...
- from unittest import TestCase
from unittest import TestCaseBigInteger/Big_Integer.py at master · YulitaGap/BigInteger https://gith ...
- https://twistedmatrix.com/documents/current/core/howto/defer.html
https://twistedmatrix.com/documents/current/core/howto/defer.html