consul是分布式的、高可用、横向扩展的。consul提供的一些关键特性:
Consul的微服务一般都是集群,集群由一个个的Consul节点组成,在这些Consul节点里面,分为两种角色,Server 以及 Client。
Consul节点在启动时可以定义自身角色,Client、Server两种。
Client节点只负责转发外部请求,所有注册到当前节点的服务会被转发到server节点,向server节点进行键值对的读/写,本身是不持久化这些信息,是无状态的;
Server节点的职责是使用raft协议保证数据一致性,响应客户端的请求,维护集群状态,与其他数据中心交互,另外所有的信息持久化到本地,这样遇到故障,信息是可以被保留的。
节点之间通过gossip广播协议(谣言协议),进行节点之间的数据交互,最终大家达到一致。
consul agent -dev -ui -node =xxx:
三个节点或五个server节点组一个集群,不建议超过五个节点,为什么是单数,因为集群需要选举一个leader来保证数据一致性。票数要超过半数以上才能选举为leader。
基本的命令为:
consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=172.16.2.100 -bind=172.16.2.100 -client=0.0.0.0 -datacenter=firstDataCenter -ui
-server 表示是以服务端身份启动
-bootstrap-expect=3 表示server集群最低节点数为3,低于这个值将工作不正常(注:类似zookeeper一样,通常集群数为奇数,方便选举,consul采用的是raft算法)
-data-dir 表示指定数据的存放目录(该目录必须存在)
-node 表示节点在web ui中显示的名称
-bind 表示绑定到哪个ip(有些服务器会绑定多块网卡,可以通过bind参数强制指定绑定的ip)
-client 指定客户端访问的ip(consul有丰富的api接口,这里的客户端指浏览器或调用方),0.0.0.0表示不限客户端ip
-datacenter 设置数据中心,这是配置代理运行的数据中心。每个节点都必须设置其它向数据中心报告
-ui
-join 选定一个IP加入集群
现在我们使用四台机器创建集群:172.16.2.100 172.16.0.118 172.16.3.190 172.16.3.69
consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=172.16.2.100 -bind=172.16.2.100 -client=0.0.0.0 -datacenter=firstDataCenter -ui
consul agent -data-dir F:\consul -node=c1 -bind=172.16.3.190 -datacenter=firstDataCenter
consul join 172.16.xx.190
成功后,会输出:
Successfully joined cluster by contacting 1 nodes.
其它2个节点(指:172.16.xx.190之外的节点)上类似上述操作,都加入集群中,完成后,可以再次验证
此处我们节点名称-node以IP命名,访问http://localhost:8500,可以看到当前有三个服务,Leader为172.16.0.118
consul agent常用命令解读
1.修改默认端口 使用-http-port命令行参数,例如修改成8080端口 consul agent -dev -http-port 8080
2.公网可访问 使用-client 0.0.0.0 consul agent -dev -http-port 8080 -client 0.0.0.0
3.查看集群节点信息 consul members Node Address Status Type Build Protocol DC Segment n3 127.0.0.0:8301 alive server 1.1.0 2
dc1node:节点名 Address:节点地址 Status:alive表示节点健康 Type:server运行状态是server状态
DC:dc1表示该节点属于DataCenter14.-data-dir 作用:指定agent储存状态的数据目录,这是所有agent都必须的,对server尤其重要,因为他们必须持久化集群的状态
5.-config-dir 作用:指定service的配置文件和检查定义所在的位置。目录必需为consul.d,文件内容都是json格式的数据。配置详解见官方
6.-config-file 作用:指定一个要装载的配置文件
7.-dev 作用:开发服务器模式,虽然是server模式,但不用于生产环境,因为不会有任何持久化操作,即不会有任何数据写入到磁盘
8.-bootstrap-expect 作用: 参数表明该服务运行时最低开始进行选举的节点数,当设置为1时,则意味允许节点为一个时也进行选举;当设置为3时,则等到3台节点同时运行consul并加入到server才能参与选举,选举完集群才能够正常工作。 一般建议服务器结点3-5个。
9.-node 作用:指定节点在集群中的名称,该名称在集群中必须是唯一的(默认这是机器的主机名),直接采用机器的IP
10.-bind 作用:指明节点的IP地址,一般是0.0.0.0或者云服务器内网地址,不能写阿里云外网地址。这是Consul侦听的地址,它必须可以被集群中的所有其他节点访问。虽然绑定地址不是绝对必要的,但最好提供一个。
11.-server 作用:指定节点为server,每个数据中心(DC)的server数推荐3-5个。
12.-client 作用:指定节点为client,指定客户端接口的绑定地址,包括:HTTP、DNS、RPC 默认是127.0.0.1,只允许回环接口访问
13.-datacenter 作用:指定机器加入到哪一个数据中心中。老版本叫-dc,-dc已经失效 consul agent常用命令解读
服务注册关键代码如下
public static class ConsulHelper
{
///
/// 服务注册到consul
///
///
///
public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IConfiguration configuration, IHostApplicationLifetime lifetime)
{
var consulClient = new ConsulClient(c =>
{
//consul地址
c.Address = new Uri(configuration["ConsulSetting:ConsulAddress"]);
});
var registration = new AgentServiceRegistration();
registration.ID = Guid.NewGuid().ToString();//服务实例唯一标识
registration.Name = configuration["ConsulSetting:ServiceName"];//服务名
registration.Address = configuration["ConsulSetting:ServiceIP"]; //服务IP
registration.Port = int.Parse(configuration["ConsulSetting:ServicePort"]);//服务端口 因为要运行多个实例,端口不能在appsettings.json里配置,在docker容器运行时传入
registration.Check = new AgentServiceCheck();
registration.Check.DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5);//服务启动多久后注册
registration.Check.Interval = TimeSpan.FromSeconds(10);//健康检查时间间隔
registration.Check.HTTP = $"http://{configuration["ConsulSetting:ServiceIP"]}:{configuration["ConsulSetting:ServicePort"]}{configuration["ConsulSetting:ServiceHealthCheck"]}";//健康检查地址
registration.Check.Timeout = TimeSpan.FromSeconds(5);//超时时间
//服务注册
consulClient.Agent.ServiceRegister(registration).Wait();
//应用程序终止时,取消注册
lifetime.ApplicationStopping.Register(() =>
{
consulClient.Agent.ServiceDeregister(registration.ID).Wait();
});
return app;
}
}
心跳,提供给consul心跳检测的接口,代码如下
[Route("[controller]")]
[ApiController]
public class HealthCheckController : ControllerBase
{
///
/// 健康检查接口
///
///
[HttpGet]
public IActionResult Get()
{
return Ok();
}
}
客户端服务发现代码如下
public class Program
{
public static void Main(string[] args)
{
// 服务发现
List<string> targets = FindServiceEndpoints("OrderService");
foreach (var item in targets)
{
Console.WriteLine(item);
}
List<string> targets1 = FindServiceEndpoints("ProductService");
foreach (var item in targets1)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
static List<string> FindServiceEndpoints(string serviceName)
{
var _client = new ConsulClient(config =>
{
var uriBuilder = new UriBuilder("http://localhost:8500");
config.Address = uriBuilder.Uri;
});
var targets = new List<string>();
try
{
var r = _client.Health.Service(serviceName, "", true).Result;
if (r.StatusCode != HttpStatusCode.OK)
throw new ApplicationException($"query consul server error");
targets = r.Response.Select(x => $"{x.Service.Address}:{x.Service.Port}").ToList();
}
catch { }
return targets;
}
}
https://gitee.com/huage2331/consuldemo