Consul 的基本使用与集群搭建
作者:神秘码农
- 2022 年 5 月 07 日
本文字数:7316 字
阅读完需:约 24 分钟
@[toc]
一、注册中心的概念
概念能够注册微服务地址【ip:端口】的组件就是注册中心。如图:
目的保证微服务的动态伸缩性。
二、注册中心的使用场景
场景主要场景是在微服务中使用。如图:
三、注册中心的技术选型
类型
zookeeper
consul
etcd
eureka
特点
Consul 的三个概念
server:存储微服务地址【ip:端口】
client:连接 Consul
agent:后台服务
应用架构集成原理如图:
四、注册中心的项目落地
工具
Consul 网盘下载地址:链接:https://pan.baidu.com/s/1zN4PiFVuNAPysMabKdDkzg 提取码:lnk7
demo 项目
步骤
Consul 运行命令
# 在根目录下启动运行
consul.exe agent -dev #在开发模式下启动命令
consul agent -server -bootstrap-expect [节点数据量] -data-dir d:/consul/data [数据存储地址]
复制代码
运行结果如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/4d3b15fd85b845d19506b9c42c0cb865.png#pic_center)
复制代码
demo 项目
nuget 安装
Consul
复制代码
- appsettings.json 添加配置信息
复制代码
{
......
"ConsulRegistry": {
"Name": "testService",
"RegistryAddress": "http://127.0.0.1:8500",
"HealthCheckAddress": "/HealthCheck"
}
}
复制代码
- 新增配置实体类,通过json文件映射到实体配置类
复制代码
public class ServiceRegistryConfig
{
/// <summary>
/// 服务ID
/// </summary>
public string Id {get;set;}
/// <summary>
/// 服务名称
/// </summary>
public string Name {get;set;}
/// <summary>
/// 服务标签
/// </summary>
public string[] Tags { get; set; }
/// <summary>
/// 服务地址
/// </summary>
public string Address { get; set; }
/// <summary>
/// 服务端口号
/// </summary>
public int Port { get; set; }
/// <summary>
/// 服务注册地址
/// </summary>
public string RegistryAddress { get; set; }
/// <summary>
/// 服务健康检查地址
/// </summary>
public string HealthCheckAddress { get; set; }
}
复制代码
- 微服务注册
- 创建服务注册实现类
复制代码
public class ServiceRegistry : IServiceRegistry
{
public void Register(ServiceRegistryConfig serviceRegistryConfig)
{
//1 建立consul客户端的连接
var consulClient = new ConsulClient(configuration =>
{
configuration.Address = new Uri(serviceRegistryConfig.RegistryAddress);
});
//2 创建 consul服务注册对象
var registration = new AgentServiceRegistration()
{
ID = serviceRegistryConfig.Id,
Name = serviceRegistryConfig.Name,
Address = serviceRegistryConfig.Address,
Port = serviceRegistryConfig.Port,
Tags = serviceRegistryConfig.Tags,
//健康检查
Check = new AgentServiceCheck()
{
//设置健康检查超时时间
Timeout = TimeSpan.FromSeconds(10),
//服务停止5秒后注销服务
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(50),
//健康检查地址
HTTP = serviceRegistryConfig.HealthCheckAddress,
//健康检查间隔时间
Interval = TimeSpan.FromSeconds(10)
}
};
//服务注册
consulClient.Agent.ServiceRegister(registration);
//关闭连接释放资源
consulClient.Dispose();
}
/// <summary>
/// 注册中心注销
/// </summary>
/// <param name="serviceRegistryConfig"></param>
public void Deregister(ServiceRegistryConfig serviceRegistryConfig)
{
var consulClient = new ConsulClient(configuration => {
configuration.Address = new Uri(serviceRegistryConfig.Address);
});
consulClient.Agent.ServiceDeregister(serviceRegistryConfig.Id);
}
}
复制代码
- 创建服务注册看接口类
复制代码
public interface IServiceRegistry
{
void Register(ServiceRegistryConfig serviceRegistryConfig);
void Deregister(ServiceRegistryConfig serviceRegistryConfig);
}
复制代码
- 创建服务注册扩展类
复制代码
//consul服务注册类
public static class ConsulExtensions
{
/// <summary>
/// 注册中心扩展
/// </summary>
/// <param name="services"></param>
/// <param name="Configuration"></param>
/// <returns></returns>
public static IServiceCollection AddConsul(this IServiceCollection services, IConfiguration Configuration)
{
//将json文件映射到实体类
services.Configure<ServiceRegistryConfig>(Configuration.GetSection("ConsulRegistry"));
services.AddSingleton<IServiceRegistry, ServiceRegistry>();
return services;
}
}
// 服务启动时注册服务
public static class ConsulApplicationBuilderExtension
{
public static IApplicationBuilder UseConsulRegistry(this IApplicationBuilder app)
{
//获取配置信息
var serviceNode = app.ApplicationServices.GetRequiredService<IOptions<ServiceRegistryConfig>>().Value;
//获取生命周期
var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
//获取服务注册实力
var consulRegistry = app.ApplicationServices.GetRequiredService<IServiceRegistry>();
//获取服务地址信息
var features = app.Properties["server.Features"] as FeatureCollection;
var address = features.Get<IServerAddressesFeature>().Addresses.First();
var uri = new Uri(address);
//服务注册
serviceNode.Id = Guid.NewGuid().ToString();
serviceNode.Address = $"{uri.Scheme}://{ uri.Host}";
serviceNode.Port = uri.Port;
serviceNode.HealthCheckAddress = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceNode.HealthCheckAddress}";
consulRegistry.Register(serviceNode);
//服务器关闭时注销服务
lifetime.ApplicationStopping.Register(() => {
consulRegistry.Deregister(serviceNode);
});
return app;
}
}
//在startup类中ConfigureServices 方法中注册服务
services.AddConsul(Configuration);
//在startup类中Configure 方法启动服务
app.UseConsulRegistry();
复制代码
运行结果如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/48e399c4c1174b8aaa0d54ee1fcedffb.png#pic_center)
- 微服务发现
- 在appsettings.json 文件中新增Consul注册地址配置
复制代码
......
"ConsulDiscoverys": {
"RegistryAddress": "http://127.0.0.1:8500"
}
.....
复制代码
- 新建配置类
复制代码
public class ServiceDiscoveryConfig
{
public string RegistryAddress { get; set; }
}
复制代码
- 新增服务发现接口类
复制代码
public interface IConsulDiscovery
{
Task<List<ServiceUrl>> Discovery(string ServiceName);
}
复制代码
- 新增服务发现实现类
复制代码
public class ConsulDiscovery : IConsulDiscovery
{
private readonly IConfiguration Configuration;
public ConsulDiscovery(IConfiguration _Configuration) {
Configuration = _Configuration;
}
/// <summary>
/// 服务发现
/// </summary>
/// <param name="ServiceName">服务名称</param>
/// <returns>返回一个集合</returns>
public async Task<List<ServiceUrl>> Discovery(string ServiceName)
{
List<ServiceUrl> list = new List<ServiceUrl>();
ServiceDiscoveryConfig serviceDiscoveryConfig = new ServiceDiscoveryConfig();
serviceDiscoveryConfig = Configuration.GetSection("ConsulDiscoverys").Get< ServiceDiscoveryConfig >();
//1 建立连接
var consulClient = new ConsulClient(Options => {
Options.Address = new Uri(serviceDiscoveryConfig.RegistryAddress);
});
// 2 根据服务名称获取注册的服务地址
var queryResult = await consulClient.Catalog.Service("ServiceName");
// 3 将注册的地址注入集合中
foreach (var item in queryResult.Response)
{
list.Add(new ServiceUrl() { Url = item.Address+":"+ item.ServicePort });
}
return list;
}
}
复制代码
- 在扩展类中新增发现服务的扩展
复制代码
public static IServiceCollection AddConsulDiscovery(this IServiceCollection services)
{
services.AddSingleton<IConsulDiscovery, ConsulDiscovery>();
return services;
}
复制代码
- 在Startup类ConfigureServices方法中进行注册
复制代码
//服务发现
services.AddConsulDiscovery();
复制代码
- 在控制器构造函数中注入下服务发现的接口
复制代码
private readonly IConsulDiscovery consulDiscovery;
public HomeController(IConsulDiscovery _consulDiscovery)
{
consulDiscovery = _consulDiscovery;
}
.....
//然后在其他方法中根据服务名称获取服务地址;注意:返回值是一个集合。
复制代码
五、注册中心 Consul 的高可用
集群搭建 【最好有 3 个实例】
步骤
节点 1
# 1、新建配置文件,路径:D:/Assembly/Consul/node1/basic.json
{ "datacenter": "dc1", "data_dir": "D:/Assembly/Consul/node1", "log_level": "INFO", "server": true, "node_name": "node1", "ui": true, "bind_addr": "127.0.0.1", "client_addr": "127.0.0.1", "advertise_addr": "127.0.0.1", "bootstrap_expect": 3, "ports":{ "http": 8500, "dns": 8600, "server": 8300, "serf_lan": 8301, "serf_wan": 8302}}
# 2、运行命令
# 2、切换到consul根目录下:
consul.exe agent -config-file=D:/Assembly/Consul/node1/basic.json
复制代码
- 节点2
复制代码
# 1、新建配置文件,路径:D:/Assembly/Consul/node2/basic.json
{ "datacenter": "dc1", "data_dir": "D:/Assembly/Consul/node2", "log_level": "INFO", "server": true, "node_name": "node2", "bind_addr": "127.0.0.1", "client_addr": "127.0.0.1", "advertise_addr": "127.0.0.1", "ports":{ "http": 8510, "dns": 8610, "server": 8310, "serf_lan": 8311, "serf_wan": 8312}}
# 2、切换到consul根目录下:
consul.exe agent -config-file=D:/Assembly/Consul/node2/basic.json -retry-join=127.0.0.1:8301
复制代码
- 节点3
复制代码
# 1、新建配置文件,路径:文件地址:D:/Assembly/Consul/node3/basic.json
{ "datacenter": "dc1", "data_dir": "D:/Assembly/Consul/node3", "log_level": "INFO", "server": true, "node_name": "node3", "bind_addr": "127.0.0.1", "client_addr": "127.0.0.1", "advertise_addr": "127.0.0.1", "ports":{ "http": 8520, "dns": 8620, "server": 8320, "serf_lan": 8321, "serf_wan": 8322}}
# 2、切换到consul根目录下:
consul.exe agent -config-file=D:/Assembly/Consul/node3/basic.json -retry-join=127.0.0.1:8301
复制代码
运行结果如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/0a5a693483e844ee84f1bd238ffe9a00.png#pic_center)
复制代码
查看主节点
#切换到consul根目录下
consul.exe info
复制代码
集群搭建命令
-bind:为该节点绑定一个地址
-enable-script-checks=true:设置检查服务为可用
-join:加入到已有的集群中
-server 表示当前使用的server模式
-node:指定当前节点在集群中的名称
-config-file - 要加载的配置文件
-config-dir:指定配置文件,定义服务的,默认所有以.json结尾的文件都会读
-datacenter: 数据中心没名称,不设置的话默认为dc
-client: 客户端模式
-ui: 使用consul自带的ui界面
-data-dir consul存储数据的目录
-bootstrap:用来控制一个server是否在bootstrap模式,在一个datacenter中只能有一个server处于bootstrap模式,当一个server处于bootstrap模式时,可以自己选举为raft leader。
-bootstrap-expect:在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群,该标记不能和bootstrap公用
这两个参数十分重要, 二选一,如果两个参数不使用的话,会出现就算你使用join将agent加入了集群仍然会报
2018/10/14 15:40:00 [ERR] agent: failed to sync remote state: No cluster leader
复制代码
配置文件参数
ui: 相当于-ui 命令行标志。
acl_token:agent会使用这个token和consul server进行请求
acl_ttl:控制TTL的cache,默认是30s
addresses:一个嵌套对象,可以设置以下key:dns、http、rpc
advertise_addr:等同于-advertise
bootstrap:等同于-bootstrap
bootstrap_expect:等同于-bootstrap-expect
bind_addr:等同于-bindca_file:提供CA文件路径,用来检查客户端或者服务端的链接
cert_file:必须和key_file一起
check_update_interval:
client_addr:等同于-client
datacenter:等同于-dc
data_dir:等同于-data-dir
disable_anonymous_signature:在进行更新检查时禁止匿名签名
enable_debug:开启debug模式
enable_syslog:等同于-syslog
encrypt:等同于-encrypt
key_file:提供私钥的路径
leave_on_terminate:默认是false,如果为true,当agent收到一个TERM信号的时候,它会发送leave信息到集群中的其他节点上。
log_level:等同于-log-level node_name:等同于-node
ports:这是一个嵌套对象,可以设置以下key:dns(dns地址:8600)、http(http api地址:8500)、rpc(rpc:8400)、serf_lan(lan port:8301)、serf_wan(wan port:8302)、server(server rpc:8300)
protocol:等同于-protocol
rejoin_after_leave:等同于-rejoin
retry_join:等同于-retry-join
retry_interval:等同于-retry-interval
server:等同于-server
syslog_facility:当enable_syslog被提供后,该参数控制哪个级别的信息被发送,默认Local0
ui_dir:等同于-ui-dir
复制代码
划线
评论
复制
发布于: 刚刚阅读数: 4
版权声明: 本文为 InfoQ 作者【神秘码农】的原创文章。
原文链接:【http://xie.infoq.cn/article/4ac7cfeb67fcd9fef3f1b3aa8】。未经作者许可,禁止转载。
神秘码农
关注
还未添加个人签名 2022.03.14 加入
好好学习,天天向上!
评论