.net core学习笔记,组件篇:服务的注册与发现(Consul)初篇
1、什么是服务注册中心?
在学习服务注册与发现时,我们要先搞明白到底什么是服务注册与发现。
在这里我举一个生活中非常普遍的例子——网购来简单说明,网购在我们日常生活中已经是非常普遍了,其实网购中的(商家—菜鸟驿站—买家),就组成了一个非常简单的注册发现逻辑。在我们购买商品之后,需要拿到这件商品,如果是普通的点对点服务,商家直接将商品快递给买家,如果买家临时有事不在家,这个时候将会收货失败。
当引入注册中心—菜鸟驿站之后,商家发货后只需要将商品发送给菜鸟驿站(服务注册),买家在合适的时间通过快递号或者扫码去菜鸟驿站拿取自己的商品(服务发现),在这个环节中,菜鸟驿站只负责商品的收与发,这样就构成了一个简单的服务发现逻辑。
2、为什么要使用服务注册中心?
1、解耦:
服务消费者和服务提供者之间完全解耦。就如同上面的例子:买家不用去关心卖家到底发什么快递,只要我去快递驿站能拿到商品就OK。
2、扩展:
服务消费者和服务提供者增加和删除新的服务时,对于双方没有任何影响。比如:买家买了多个不同的商品,这时买家也只需要根据不同的取件凭据去菜鸟驿站拿取对应的商品就OK。
3、不同的服务注册中心组件
zookeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。ZooKeeper包含一个简单的原语集,提供Java和C的接口。
consul
Consul 是 HashiCorp 公司推出的开源产品,用于实现分布式系统的服务发现、服务隔离、服务配置,这些功能中的每一个都可以根据需要单独使用,也可以同时使用所有功能。Consul 官网目前主要推 Consul 在服务网格中的使用。
etcd
etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft
协议作为一致性算法,etcd基于Go语言实现。
eureka
eureka注册中心已经闭源,不建议在家学习使用。
4、什么是Consul
Consul是一个用来实现分布式系统的服务发现与配置的开源工具。是由go语言开发。他主要由多个组成部分:
- 服务发现:客户端通过Consul提供服务,类似于API、MySQL、或者其他客户端可以使用Consul发现服务的提供者。使用类似DNS或者HTTP,应用程序和可以很轻松的发现他们依赖的服务。
- 检查健康:Consul客户端可以提供与给定服务相关的健康检查(Web服务器返回200 ok)或者本地节点(“内存利用率低于90%”)。这些信息可以监控集群的运行情况,并且使访问远离不健康的主机组件。
- 键值对存储:应用程序可以使用Cousul的层级键值对。
- 多数据中心:Consul有开箱及用的多数据中心。
5、如何在asp.net core中使用Consul
概念性的内容已经讲的差不多了,下面我们来看看如何在asp.net core+windows下使用Consul。
5.1、下载Consul
官网地址: https://www.consul.io/
下载地址: https://releases.hashicorp.com/consul/1.7.2/ 或 https://www.consul.io/downloads.html
5.2、启动Consul
consul.exe agent -dev
参数介绍:
- Version:consul版本
- Node ID:consul当前启动的节点ID
- Node name:consul当前启动的节点名称,默认当前电脑名称
- Datacenter:数据中心
- Service:consul的启动模式,true表示服务端模式,false表示客户端模式
- Client Addr:客户端连接地址,支持HTTP、HTTPS、GRPC、DNS,默认使用HTTP
- Cluster Addr:集群地址,就是Server模式下的启动方式
5.3、编码
5.3.1、创建两个asp.net core webapi项目,并分别引用Consul的包。
5.3.2、编写服务提供者代码
在服务提供项目(ConsulService)的Startup类的Configure方法内编写如下代码:
// 创建Consul的客户端连接
var consulClient = new ConsulClient(configuration =>
{
// Consul的连接地址
configuration.Address = new Uri("http://127.0.0.1:8500");
});
// 创建Consul的服务注册信息
var registration = new AgentServiceRegistration()
{
// 服务ID
ID = Guid.NewGuid().ToString(),
// 服务名称
Name = "demoService",
// 服务连接地址
Address = "https://localhost",
// 端口
Port = 5001
// AgentServiceRegistration对象还有一些其他属性,后面有机会再了解
};
// 注册服务
consulClient.Agent.ServiceRegister(registration);
然后启动项目:
项目启动成功,我们访问Consul的可视化web页面(地址默认是8500端口),看服务是否注册成功:
从上面的截图可以看到,我们刚刚注册的demoService服务已经注册成功了。
5.3.3、编写服务消费者代码
在服务消费者项目中添加一个Service文件夹,新增一个服务消费的接口然后实现这个接口:
public interface IDemoService
{
Task<string> GetDemoService();
}
public class DemoService : IDemoService
{
private readonly IHttpClientFactory httpClientFactory;
public DemoService(IHttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory;
}
public async Task<string> GetDemoService()
{
var res = "";
// 创建consul连接对象
var consulClient = new Consul.ConsulClient(configuare =>
{
// Consul的连接地址
configuare.Address = new Uri("http://127.0.0.1:8500");
});
// 根据刚才注册的服务名称获取对应的服务
var queryResult = await consulClient.Catalog.Service("demoService");
// 服务连接地址
var serviceUrls = new List<string>();
// 遍历获取到的服务列表
foreach (var service in queryResult.Response)
{
// 拼接连接地址
serviceUrls.Add(service.ServiceAddress + ":" + service.ServicePort);
}
HttpClient httpClient = httpClientFactory.CreateClient();
HttpResponseMessage response = await httpClient.GetAsync(serviceUrls[0] + "/api/Home/");
if (response.StatusCode == HttpStatusCode.OK)
{
res = await response.Content.ReadAsStringAsync();
}
return res;
}
}
在控制器调用这个服务:
private readonly ILogger<HomeController> _logger;
private readonly IDemoService _demoService;
public HomeController(ILogger<HomeController> logger, IDemoService demoService)
{
_logger = logger;
_demoService = demoService;
}
[HttpGet]
public Task<string> Get()
{
return _demoService.GetDemoService();
}
注意,记得在Startup类中的ConfigureService方法中注入上面的服务接口与类,具体为什么要注入应该不用我多说了。
1 services.AddScoped<IDemoService, DemoService>();
最后,我们启动消费者项目,并请求对应接口看看效果,很显然,服务已经请求成功。
这篇文章暂时就到这里,上面就是.net core对Consul最简单的应用。随着学习的深入,后面会有相应的学习笔记记录。
因为本人也是处于探索阶段,上面所写的也仅仅是一些学习笔记,所以一些理解可能不够准确,希望所写的一些内容出现错误大家能给予包容和指正。
- 使用JDBC向Kudu表插入中文字符-双引号的秘密
- Yarn的JobHistory目录权限问题导致MapReduce作业异常
- 输入一个数字,然后计算出从1到输入数字的和,要求,如果输入的数字小于1,则重新输入,直到输入正确的数字为止
- Linux基础(day76)
- zabbix设置QQ邮箱告警
- 关于JSON CSRF的一些思考
- linux学习第七十篇:expect脚本同步文件,expect脚本指定host和要同步的文件,构建文件分发系统,批量远程执行命令
- linux学习第六十九篇:分发系统介绍,expect脚本远程登录,expect脚本远程执行命令,expect脚本传递参数
- linux学习第六十八篇:告警系统邮件引擎,运行告警系统
- linux学习第六十七篇:告警系统主脚本,告警系统配置文件,告警系统监控项目
- linux学习第六十六篇:shell中的函数,shell中的数组,告警系统需求分析
- linux学习第六十五篇:for循环,while循环, break跳出循环,continue结束本次循环
- linux学习第六十四篇:Shell脚本中的逻辑判断,文件目录属性判断, if特殊用法,case判断
- linux学习第六十三篇:Shell脚本介绍,Shell脚本结构和执行,date命令用法,Shell脚本中的变量
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- pytorch实现查看当前学习率
- python3.x中安装web.py步骤方法
- pytorch 网络参数 weight bias 初始化详解
- PHP中单例模式的使用场景与使用方法讲解
- pytorch查看模型weight与grad方式
- php+ajax 文件上传代码实例
- PHP将整数数字转换为罗马数字实例分享
- PHP如何通过表单直接提交大文件详解
- PHP基于openssl实现的非对称加密操作示例
- python图片验证码识别最新模块muggle_ocr的示例代码
- virtualenv介绍及简明教程
- Keras 数据增强ImageDataGenerator多输入多输出实例
- TensorFlow中如何确定张量的形状实例
- 使用Dajngo 通过代码添加xadmin用户和权限(组)
- python和js交互调用的方法