在阅读本文前我想您应该对微服务架构有一个基本的或者模糊的了解html
Consul是一个服务管理软件,它其实有不少组件,包括服务发现配置共享键值对存储等node
本文主要讲解Consul的服务注册服务发现以及集群的配置web
参考资料:bootstrap
https://blog.csdn.net/younger_china/article/details/79462530windows
https://www.cnblogs.com/shanyou/p/6286207.htmlapi
假设有服务A,B,C.服务A须要调用服务B和C,传统的方式咱们须要在服务A中记录服务B和C的ip及端口号。这些配置通常写在配置文件等地方存储。缓存
这种作法有两个显而易见的缺点:1.若是未来B的ip改变了就须要修改全部调用者的ip配置。 2.难以作负载均衡服务器
而服务发现就是用来解决这个问题的,怎么解决呢?请看下面这张图网络
这张图中在服务消费者和服务生产者之间加了一个服务注册中心的模块,用上面的服务器ABC来举例,服务B在发布的时候会在注册中心注册,注册中心会记录服务B的名字及ip地址。当服务A请求服务B的时候,只须要带着服务B的名字来注册中心查询便可。集群状况下,注册中心会有多个服务B。同时注册中心会按期检查每个服务否能够正常访问,移除不可访问的服务。(健康检查)架构
总的来讲,服务发现就是经过一个标志来获取服务列表,而且服务列表可随着每一个服务的上线或下线动态变动
下面列出几个consul中出现频率较高的术语
Agent,Agent是长期运行在每一个consul集群成员节点上守护进程。经过命令consul agent启动。Agent有client和server两种模式。因为每一个节点都必须运行agent,全部节点要么是client要么是server。全部的Agent均可以能够调用DNS或HTTP API,并负责检查和维护服务同步。
client 运行client模式的Agent,将全部的RPCs转发到Server。Client是相对无状态的。Client惟一所作的是在后台参与LAN gossip pool。只消耗少许的资源,少许的网络带宽。
Server 运行Server模式的Agent,参与Raft quorum,维护集群的状态,响应RPC查询,与其余数据中心交互WAN gossip,转发查询到Leader或远程数据中心。
datacenter 数据中心的定义彷佛是显而易见的,有一些细节是必须考虑的。例如,在EC2,多个可用性区域是否被认为组成了单一的数据中心?咱们定义数据中心是在同一个网络环境中——私有的,低延迟,高带宽。这不包括基于公共互联网环境,可是对于咱们而言,在同一个EC2的多个可用性区域会被认为是一个的数据中心。
关于client和server我搞了很久才搞明白,实际上client不存储数据,发送到client的请求,client都会转发给它绑定的server,也就是说client必须绑定server。server会存储数据,若是只有一个server并在上面注册了一个服务,这个server挂了而后你又重启了,那么这个服务的注册信息仍然保存在server上。
若是你在一台服务器上运行了一个server,它会默认有一个client绑定到server上,而且地址是127.0.0.1
consul下载地址:https://www.consul.io/downloads.html
我用的win10 系统,因此下载的最后一个windows64位的,下载下来有个exe文件,随便放个到一个文件夹下就能够了。
进入cmd,转到consul的存放目录,打命令就能够了。
或者能够把consul的目录路径加入到Path环境变量中,就不用每次到目录下打命令了
上面说过,consul能够以client和server的方式启动
Server:consul agent -server -bootstrap-expect 1 -data-dir=C:\consul -node=n1 -bind=192.168.3.233 -ui-dir=C:\consul\dist -client=0.0.0.0
Client:consul agent -bootstrap-expect 1 -data-dir=C:\consul -node=n1 -bind=192.168.3.233 -ui-dir=C:\consul\dist
把**-server**去掉就是client模式了
- consul agent:启动consul的命令,要么是server要么是client
- -bootstrap-expect:指望的server节点数目,若是集群中的server节点小于这个数据,集群则失效,而且该server也失效,一直等到集群中的数目达到相应的数量才生效,若是是1的话,表明一个server就能够了
- -data-dir:data存放的目录,server会保存一些配置缓存等信息,存在此目录下
- -node:该节点的名称,急群众名称必须惟一
- -client:表明该server对外暴漏的client地址,0.0.0.0表明我能够经过:127.0.0.1和192.168.3.233访问,不设置的话默认是:127.0.0.1
- -bind:这是设置集群中server之间互相通讯的地址,必须能够互相访问到
- -ui-dir:设置webui的界面,理论上经过命令能够查看到咱们须要的任何信息,可是经过ui来查看更直观
我开启了两台虚拟机和本机一共是三台机器,因此我搭建了三个server节点
Ser1:consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node1 -bind=192.168.3.233 -client=0.0.0.0
Ser2:consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node2 -join=192.168.3.233 -bind=192.168.3.201 -client=0.0.0.0
Ser3: consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node3 -join=192.168.3.233 -bind=192.168.3.243 -client=0.0.0.0
-join:表示加入到哪一个集群内,ser2中咱们指定加入到了ser1中,这时候ser1和ser2组成了集群,ser3咱们能够指定加入到ser1和ser2,无论加入哪一个最终这三个server都组成了一个集群,最终三个server商量了一下选出了一个leader
能够经过命令来注册服务,由于最终是要在.net core上使用,因此我就直接贴上.net core中的相关代码
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifeTime) { string ip = Configuration["ip"]; string port = Configuration["port"]; string serviceName = "MsgService"; string serviceId = serviceName + Guid.NewGuid(); Action<ConsulClientConfiguration> ConsulConfig = (config) => { config.Address = new Uri("http://192.168.3.201:8500"); //服务注册的地址,集群中任意一个地址 config.Datacenter = "dc1"; }; using (var consulClient = new ConsulClient(ConsulConfig)) { AgentServiceRegistration asr = new AgentServiceRegistration { Address = ip, Port = Convert.ToInt32(port), ID = serviceId, Name = serviceName, Check = new AgentServiceCheck { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), HTTP = $"http://{ip}:{port}/api/Health",//健康检查访问的地址 Interval = TimeSpan.FromSeconds(10), //健康检查的间隔时间 Timeout = TimeSpan.FromSeconds(5), //多久表明超时 }, }; consulClient.Agent.ServiceRegister(asr).Wait(); } //注销Consul appLifeTime.ApplicationStopped.Register(() => { using (var consulClient = new ConsulClient(ConsulConfig)) { consulClient.Agent.ServiceDeregister(serviceId).Wait(); //从consul集群中移除服务 } }); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseMvc(); }
运行程序后向consul集群注册了一个服务,访问集群的任何一个ip均可取到该服务的ip。客户端查询服务的代码以下:
static void Main(string[] args) { using (var consul = new Consul.ConsulClient(c => { c.Address = new Uri("http://192.168.3.233:8500"); //Consul地址 })) { var services = consul.Catalog.Service("MsgService").Result.Response; foreach (var s1 in services) { Console.WriteLine($"ID={s1.ServiceID},Service={s1.ServiceName},Addr={s1.Address},Port={s1.ServicePort}"); } } }
这样咱们一个基本的consul集群就能够正常使用了
对于consul和服务发现目前还只是刚刚开始接触。仍是有不少问题暂时没有搞明白。
好比客户端链接的server忽然挂了怎么办如何切换到另外一个server?以及一个服务下线了如何通知客户端删除缓存等等。还请你们不吝赐教