.NET Core微服务之路:基于Consul最少集群实现服务的注册与发现(一)
Consul介绍
Consul是HashiCorp公司推出的开源工具[开源地址:https://github.com/hashicorp/consul],用于实现分布式系统的服务发现与配置。
与市面上其他系统比较如下:
总体而言, Consul用Golang实现,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与Docker等轻量级容器可无缝配合。
此外,关于Consul的架构以及相关的角色,如下图所示:
以Server模式运行的Consul Agent节点用于维护Consul集群的状态,官方建议每个Consul Cluster至少有3个或以上的运行在Server Mode的Agent,Client节点不限。Consul支持多数据中心,每个数据中心的Consul Cluster都会在运行于Server模式下的Agent节点中选出一个Leader节点,这个选举过程通过Consul实现的raft协议保证,多个 Server节点上的Consul数据信息是强一致的。处于Client Mode的Consul Agent节点比较简单,无状态,仅仅负责将请求转发给Server Agent节点。
集群搭建
笔者打算通过五台Centos7来搭建Consul集群,借助VMware Workstation搭建,当然,最主要的是这台虚拟主机一定要相互ping通,最好关闭防火墙,而且,虚拟机也需要和宿主机(实比如笔者的Windows10操作系统)ping通,具体问题和配置可搜索一下,图片如下:
其中130作为leader角色,129和131作为follower角色,当然,在实际环境中,leader的角色不一定是固定的,会随着环境变化而变化(比如网络断了、宕机了等等)这个我们后续来验证。132和133作为客户端,并安装NET Core 2.1环境,再次提示,一定要保证在这个环境中的所有系统相互之间均能Ping通。
step1:关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
step2:安装consul
wget https://releases.hashicorp.com/consul/1.3.0/consul_1.3.0_linux_amd64.zip unzip consul_1.3.0_linux_amd64.zip
step3:节点1
./consul agent -server -ui -bootstrap-expect=3 -data-dir=/tmp/consul -node=consul-1 -client=0.0.0.0 -bind=192.168.153.129 -datacenter=dc1 #设置129为服务器
bootstrap_expect > 0: expecting 3 servers ==> Starting Consul agent... ==> Consul agent running! Version: 'v1.3.0' Node ID: 'c612a043-8906-d6e1-8f4b-ef1c8afb371b' Node name: 'consul-1' Datacenter: 'dc1' (Segment: '<all>') Server: true (Bootstrap: false) Client Addr: [0.0.0.0] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600) Cluster Addr: 192.168.153.129 (LAN: 8301, WAN: 8302) Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false ==> Log data will now stream in as it occurs: 2018/10/15 04:53:30 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:c612a043-8906-d6e1-8f4b-ef1c8afb3777 Address:192.168.153.131:8300} {Suffrage:Voter ID:c612a043-8906-d6e1-8f4b-ef1c8afb371a Address:192.168.153.130:8300} {Suffrage:Voter ID:c612a043-8906-d6e1-8f4b-ef1c8afb371b Address:192.168.153.129:8300}] 2018/10/15 04:53:30 [INFO] serf: EventMemberJoin: consul-1.dc1 192.168.153.129 2018/10/15 04:53:30 [INFO] serf: EventMemberJoin: consul-1 192.168.153.129 2018/10/15 04:53:30 [WARN] agent: Service name "LZZ.DEV.ClientService" will not be discoverable via DNS due to invalid characters. Valid characters include all alpha-numerics and dashes. 2018/10/15 04:53:30 [WARN] agent: Service name "LZZ.PRO.ClientService" will not be discoverable via DNS due to invalid characters. Valid characters include all alpha-numerics and dashes. 2018/10/15 04:53:30 [WARN] agent: check 'service:17947fbe-24ee-40e1-8e49-ea42415ada23' has deregister interval below minimum of 1m0s 2018/10/15 04:53:30 [WARN] agent: check 'service:81d5b247-73d1-4ae5-9d1a-208770ca4e6a' has deregister interval below minimum of 1m0s 2018/10/15 04:53:30 [INFO] agent: Started DNS server 0.0.0.0:8600 (udp) 2018/10/15 04:53:30 [INFO] raft: Node at 192.168.153.129:8300 [Follower] entering Follower state (Leader: "") 2018/10/15 04:53:30 [INFO] serf: Attempting re-join to previously known node: consul-3.dc1: 192.168.153.131:8302 2018/10/15 04:53:30 [INFO] serf: Attempting re-join to previously known node: LZZ.PRODUCTS.WebServer: 192.168.153.133:8301 2018/10/15 04:53:30 [INFO] consul: Adding LAN server consul-1 (Addr: tcp/192.168.153.129:8300) (DC: dc1) 2018/10/15 04:53:30 [INFO] consul: Raft data found, disabling bootstrap mode 2018/10/15 04:53:30 [INFO] consul: Handled member-join event for server "consul-1.dc1" in area "wan" 2018/10/15 04:53:30 [WARN] agent/proxy: running as root, will not start managed proxies 2018/10/15 04:53:30 [INFO] agent: Started DNS server 0.0.0.0:8600 (tcp) 2018/10/15 04:53:30 [INFO] agent: Started HTTP server on [::]:8500 (tcp) 2018/10/15 04:53:30 [INFO] agent: started state syncer 2018/10/15 04:53:30 [INFO] serf: Attempting re-join to previously known node: consul-3: 192.168.153.131:8301 2018/10/15 04:53:30 [INFO] serf: EventMemberJoin: consul-3.dc1 192.168.153.131 2018/10/15 04:53:30 [WARN] memberlist: Refuting an alive message 2018/10/15 04:53:30 [INFO] serf: EventMemberJoin: consul-2.dc1 192.168.153.130 2018/10/15 04:53:30 [INFO] serf: Re-joined to previously known node: consul-3.dc1: 192.168.153.131:8302 2018/10/15 04:53:30 [INFO] consul: Handled member-join event for server "consul-3.dc1" in area "wan" 2018/10/15 04:53:30 [INFO] consul: Handled member-join event for server "consul-2.dc1" in area "wan" 2018/10/15 04:53:30 [INFO] serf: EventMemberJoin: consul-3 192.168.153.131 2018/10/15 04:53:30 [WARN] memberlist: Refuting a suspect message (from: consul-1) 2018/10/15 04:53:30 [INFO] serf: EventMemberJoin: consul-2 192.168.153.130 2018/10/15 04:53:30 [INFO] serf: Re-joined to previously known node: consul-3: 192.168.153.131:8301 2018/10/15 04:53:30 [INFO] consul: Adding LAN server consul-3 (Addr: tcp/192.168.153.131:8300) (DC: dc1) 2018/10/15 04:53:30 [INFO] consul: Adding LAN server consul-2 (Addr: tcp/192.168.153.130:8300) (DC: dc1)
Client Addr的地址是[0.0.0.0],代表本机上的所有IPv4地址。集群地址是:192.168.153.129。稍后我们介绍命令一些主要参数的的作用。
step4:节点2
./consul agent -server -ui -bootstrap-expect=3 -data-dir=/tmp/consul -node=consul-2 -client=0.0.0.0 -bind=192.168.153.130 -datacenter=dc1 -join 192.168.153.129 # join 加入到129中
bootstrap_expect > 0: expecting 3 servers ==> Starting Consul agent... ==> Joining cluster... Join completed. Synced with 1 initial agents ==> Consul agent running! Version: 'v1.3.0' Node ID: 'c612a043-8906-d6e1-8f4b-ef1c8afb371a' Node name: 'consul-2' Datacenter: 'dc1' (Segment: '<all>') Server: true (Bootstrap: false) Client Addr: [0.0.0.0] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600) Cluster Addr: 192.168.153.130 (LAN: 8301, WAN: 8302) Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false ==> Log data will now stream in as it occurs: 2018/10/15 04:56:36 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:c612a043-8906-d6e1-8f4b-ef1c8afb3777 Address:192.168.153.131:8300} {Suffrage:Voter ID:c612a043-8906-d6e1-8f4b-ef1c8afb371a Address:192.168.153.130:8300} {Suffrage:Voter ID:c612a043-8906-d6e1-8f4b-ef1c8afb371b Address:192.168.153.129:8300}] 2018/10/15 04:56:36 [INFO] serf: EventMemberJoin: consul-2.dc1 192.168.153.130 2018/10/15 04:56:36 [INFO] serf: EventMemberJoin: consul-2 192.168.153.130 2018/10/15 04:56:36 [INFO] raft: Node at 192.168.153.130:8300 [Follower] entering Follower state (Leader: "") 2018/10/15 04:56:36 [INFO] serf: Attempting re-join to previously known node: consul-3.dc1: 192.168.153.131:8302 2018/10/15 04:56:36 [INFO] serf: Attempting re-join to previously known node: consul-3: 192.168.153.131:8301 2018/10/15 04:56:36 [INFO] consul: Adding LAN server consul-2 (Addr: tcp/192.168.153.130:8300) (DC: dc1) 2018/10/15 04:56:36 [INFO] consul: Raft data found, disabling bootstrap mode 2018/10/15 04:56:36 [INFO] consul: Handled member-join event for server "consul-2.dc1" in area "wan" 2018/10/15 04:56:36 [WARN] memberlist: Refuting a suspect message (from: consul-2) 2018/10/15 04:56:36 [INFO] serf: EventMemberJoin: consul-1 192.168.153.129 2018/10/15 04:56:36 [INFO] serf: EventMemberJoin: consul-3 192.168.153.131 2018/10/15 04:56:36 [INFO] serf: Re-joined to previously known node: consul-3: 192.168.153.131:8301 2018/10/15 04:56:36 [INFO] consul: Adding LAN server consul-1 (Addr: tcp/192.168.153.129:8300) (DC: dc1) 2018/10/15 04:56:36 [INFO] consul: Adding LAN server consul-3 (Addr: tcp/192.168.153.131:8300) (DC: dc1) 2018/10/15 04:56:36 [WARN] memberlist: Refuting a suspect message (from: consul-2.dc1) 2018/10/15 04:56:36 [INFO] serf: EventMemberJoin: consul-1.dc1 192.168.153.129 2018/10/15 04:56:36 [INFO] serf: EventMemberJoin: consul-3.dc1 192.168.153.131 2018/10/15 04:56:36 [INFO] serf: Re-joined to previously known node: consul-3.dc1: 192.168.153.131:8302 2018/10/15 04:56:36 [INFO] consul: Handled member-join event for server "consul-1.dc1" in area "wan" 2018/10/15 04:56:36 [INFO] consul: Handled member-join event for server "consul-3.dc1" in area "wan" 2018/10/15 04:56:36 [INFO] agent: Started DNS server 0.0.0.0:8600 (udp) 2018/10/15 04:56:36 [WARN] agent/proxy: running as root, will not start managed proxies 2018/10/15 04:56:36 [INFO] agent: Started DNS server 0.0.0.0:8600 (tcp) 2018/10/15 04:56:36 [INFO] agent: Started HTTP server on [::]:8500 (tcp) 2018/10/15 04:56:36 [INFO] agent: (LAN) joining: [192.168.153.129] 2018/10/15 04:56:36 [INFO] agent: (LAN) joined: 1 Err: <nil> 2018/10/15 04:56:36 [INFO] agent: started state syncer
step5:节点3
./consul agent -server -ui -bootstrap-expect=3 -data-dir=/tmp/consul -node=consul-3 -client=0.0.0.0 -bind=192.168.153.131 -datacenter=dc1 -join 192.168.153.129
bootstrap_expect > 0: expecting 3 servers ==> Starting Consul agent... ==> Joining cluster... Join completed. Synced with 1 initial agents ==> Consul agent running! Version: 'v1.3.0' Node ID: 'c612a043-8906-d6e1-8f4b-ef1c8afb3777' Node name: 'consul-3' Datacenter: 'dc1' (Segment: '<all>') Server: true (Bootstrap: false) Client Addr: [0.0.0.0] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600) Cluster Addr: 192.168.153.131 (LAN: 8301, WAN: 8302) Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false ==> Log data will now stream in as it occurs: 2018/10/15 05:01:15 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:c612a043-8906-d6e1-8f4b-ef1c8afb3777 Address:192.168.153.131:8300} {Suffrage:Voter ID:c612a043-8906-d6e1-8f4b-ef1c8afb371b Address:192.168.153.129:8300} {Suffrage:Voter ID:c612a043-8906-d6e1-8f4b-ef1c8afb371a Address:192.168.153.130:8300}] 2018/10/15 05:01:15 [INFO] raft: Node at 192.168.153.131:8300 [Follower] entering Follower state (Leader: "") 2018/10/15 05:01:15 [INFO] serf: EventMemberJoin: consul-3.dc1 192.168.153.131 2018/10/15 05:01:15 [INFO] serf: EventMemberJoin: consul-3 192.168.153.131 2018/10/15 05:01:15 [INFO] serf: Attempting re-join to previously known node: consul-1.dc1: 192.168.153.129:8302 2018/10/15 05:01:15 [INFO] serf: Attempting re-join to previously known node: consul-1: 192.168.153.129:8301 2018/10/15 05:01:15 [INFO] consul: Adding LAN server consul-3 (Addr: tcp/192.168.153.131:8300) (DC: dc1) 2018/10/15 05:01:15 [INFO] consul: Raft data found, disabling bootstrap mode 2018/10/15 05:01:15 [INFO] consul: Handled member-join event for server "consul-3.dc1" in area "wan" 2018/10/15 05:01:15 [WARN] agent/proxy: running as root, will not start managed proxies 2018/10/15 05:01:15 [INFO] agent: Started DNS server 0.0.0.0:8600 (udp) 2018/10/15 05:01:15 [INFO] agent: Started DNS server 0.0.0.0:8600 (tcp) 2018/10/15 05:01:15 [INFO] agent: Started HTTP server on [::]:8500 (tcp) 2018/10/15 05:01:15 [INFO] agent: (LAN) joining: [192.168.153.129] 2018/10/15 05:01:15 [INFO] serf: EventMemberJoin: consul-1 192.168.153.129 2018/10/15 05:01:15 [INFO] serf: Re-joined to previously known node: consul-1: 192.168.153.129:8301 2018/10/15 05:01:15 [INFO] consul: Adding LAN server consul-1 (Addr: tcp/192.168.153.129:8300) (DC: dc1) 2018/10/15 05:01:15 [INFO] serf: EventMemberJoin: consul-1.dc1 192.168.153.129 2018/10/15 05:01:15 [INFO] serf: Re-joined to previously known node: consul-1.dc1: 192.168.153.129:8302 2018/10/15 05:01:15 [INFO] consul: Handled member-join event for server "consul-1.dc1" in area "wan" 2018/10/15 05:01:15 [INFO] agent: (LAN) joined: 1 Err: <nil> 2018/10/15 05:01:15 [INFO] agent: started state syncer
step6:客户端1
./consul agent -bind 192.168.153.132 -client 192.168.153.132 -data-dir=/tmp/consul -node LZZ.DEV.WebServer -join 192.168.153.129
==> Starting Consul agent... ==> Joining cluster... Join completed. Synced with 1 initial agents ==> Consul agent running! Version: 'v1.3.0' Node ID: 'c7125043-8906-d6e1-8f4b-ef1c8afb371b' Node name: 'LZZ.DEV.WebServer' Datacenter: 'dc1' (Segment: '') Server: false (Bootstrap: false) Client Addr: [192.168.153.132] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600) Cluster Addr: 192.168.153.132 (LAN: 8301, WAN: 8302) Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false ==> Log data will now stream in as it occurs: 2018/10/15 05:03:15 [WARN] agent: Node name "LZZ.DEV.WebServer" will not be discoverable via DNS due to invalid characters. Valid characters include all alpha-numerics and dashes. 2018/10/15 05:03:15 [INFO] serf: EventMemberJoin: LZZ.DEV.WebServer 192.168.153.132 2018/10/15 05:03:15 [INFO] agent: Started DNS server 192.168.153.132:8600 (udp) 2018/10/15 05:03:15 [WARN] agent/proxy: running as root, will not start managed proxies 2018/10/15 05:03:15 [INFO] agent: Started DNS server 192.168.153.132:8600 (tcp) 2018/10/15 05:03:15 [INFO] agent: Started HTTP server on 192.168.153.132:8500 (tcp) 2018/10/15 05:03:15 [INFO] agent: (LAN) joining: [192.168.153.129] 2018/10/15 05:03:15 [INFO] serf: EventMemberJoin: consul-1 192.168.153.129 2018/10/15 05:03:15 [INFO] serf: EventMemberJoin: consul-3 192.168.153.131 2018/10/15 05:03:15 [INFO] agent: (LAN) joined: 1 Err: <nil> 2018/10/15 05:03:15 [INFO] agent: started state syncer 2018/10/15 05:03:15 [INFO] consul: adding server consul-1 (Addr: tcp/192.168.153.129:8300) (DC: dc1) 2018/10/15 05:03:15 [INFO] consul: adding server consul-3 (Addr: tcp/192.168.153.131:8300) (DC: dc1) 2018/10/15 05:03:15 [INFO] agent: Synced node info
step6:客户端2
./consul agent -bind 192.168.153.133 -client 192.168.153.133 -data-dir=/tmp/consul -node LZZ.PRO.WebServer -join 192.168.153.129
==> Starting Consul agent... ==> Joining cluster... Join completed. Synced with 1 initial agents ==> Consul agent running! Version: 'v1.3.0' Node ID: '1aa2a043-8906-d6e1-8f4b-ef1c8afb371b' Node name: 'LZZ.PRO.WebServer' Datacenter: 'dc1' (Segment: '') Server: false (Bootstrap: false) Client Addr: [192.168.153.133] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600) Cluster Addr: 192.168.153.133 (LAN: 8301, WAN: 8302) Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false ==> Log data will now stream in as it occurs: 2018/10/15 05:04:26 [WARN] agent: Node name "LZZ.PRO.WebServer" will not be discoverable via DNS due to invalid characters. Valid characters include all alpha-numerics and dashes. 2018/10/15 05:04:26 [INFO] serf: EventMemberJoin: LZZ.PRO.WebServer 192.168.153.133 2018/10/15 05:04:26 [INFO] agent: Started DNS server 192.168.153.133:8600 (udp) 2018/10/15 05:04:26 [WARN] agent/proxy: running as root, will not start managed proxies 2018/10/15 05:04:26 [INFO] agent: Started DNS server 192.168.153.133:8600 (tcp) 2018/10/15 05:04:26 [INFO] agent: Started HTTP server on 192.168.153.133:8500 (tcp) 2018/10/15 05:04:26 [INFO] agent: (LAN) joining: [192.168.153.129] 2018/10/15 05:04:26 [INFO] serf: EventMemberJoin: LZZ.DEV.WebServer 192.168.153.132 2018/10/15 05:04:26 [INFO] serf: EventMemberJoin: consul-3 192.168.153.131 2018/10/15 05:04:26 [INFO] serf: EventMemberJoin: consul-1 192.168.153.129 2018/10/15 05:04:26 [INFO] agent: (LAN) joined: 1 Err: <nil> 2018/10/15 05:04:26 [INFO] agent: started state syncer 2018/10/15 05:04:26 [INFO] consul: adding server consul-3 (Addr: tcp/192.168.153.131:8300) (DC: dc1) 2018/10/15 05:04:26 [INFO] consul: adding server consul-1 (Addr: tcp/192.168.153.129:8300) (DC: dc1) 2018/10/15 05:04:26 [INFO] agent: Synced node info
- -node:节点的名称
- -bind:绑定的一个地址,用于节点之间通信的地址,可以是内外网,必须是可以访问到的地址
- -server:这个就是表示这个节点是个server
- -client:这个表示这个节点是个client
- -bootstrap-expect:这个就是表示期望提供的SERVER节点数目,数目一达到,它就会被激活,然后就是LEADER了
这样,五台服务器上的consul均已配置和启动完成,接下来我们看看他们之间的关系
step7:查看所有consul成员
./consul members
Node Address Status Type Build Protocol DC Segment consul-1 192.168.153.129:8301 alive server 1.3.0 2 dc1 <all> consul-2 192.168.153.130:8301 failed server 1.3.0 2 dc1 <all> consul-3 192.168.153.131:8301 alive server 1.3.0 2 dc1 <all> LZZ.DEV.WebServer 192.168.153.132:8301 alive client 1.3.0 2 dc1 <default> LZZ.PRO.WebServer 192.168.153.133:8301 alive client 1.3.0 2 dc1 <default>
如上可知,129,130,131三台consul的类型均是server类型,而132和133为client类型,极小化的集群搭建成功
step8:查看服务成员类型
./consul operator raft list-peers
Node ID Address State Voter RaftProtocol consul-3 c612a043-8906-d6e1-8f4b-ef1c8afb3777 192.168.153.131:8300 follower true 3 consul-2 c612a043-8906-d6e1-8f4b-ef1c8afb371a 192.168.153.130:8300 follower true 3 consul-1 c612a043-8906-d6e1-8f4b-ef1c8afb371b 192.168.153.129:8300 leader true 3
由图中可知,129目前为leader类型,为了验证之前“leader随环境变化而变化”的论证,我特意输入了命令“reboot”,请接着继续看下去。
step9:关闭一台服务,测试leader状态
当129机器重新连上Consul后,我们再输入consul operator raft list-peers,可以看到此时的leader已经变为131的机器上面。
Node ID Address State Voter RaftProtocol consul-3 c612a043-8906-d6e1-8f4b-ef1c8afb3777 192.168.153.131:8300 leader true 3 consul-1 c612a043-8906-d6e1-8f4b-ef1c8afb371b 192.168.153.129:8300 follower true 3 consul-2 c612a043-8906-d6e1-8f4b-ef1c8afb371a 192.168.153.130:8300 follower true 3
所以,leader会随着环境的变化而变化,并且但只要超过一半的Server(这里是2/3还活着)还活着,集群是可以正常工作的。这也是为什么像Consul、ZooKeeper这样的分布式管理组件推荐我们使用3个或5个节点以上来部署的原因。
step10:通过WEB查看服务状态
我们还可以通过http://192.168.153.129:8500来查看整个集群的状态。
接下来,我们创建一个net core的webApi应用程序,来向consul注册一个服务。
创建ASP.NET Core程序
创建一个ASP.NET Web Application应用程序,项目名称自定
创建一个HealthController控制器,用于提示该服务的状态。
using Microsoft.AspNetCore.Mvc; namespace LZZ.DEV.WebServer.Controllers { [Produces("application/json")] [Route("api/Health")] public class HealthController : Controller { [HttpGet] public IActionResult Get() => Ok("ok"); } }
再创建一个应用程序扩展来建立连接和注册服务,利用Net core的管道灵活特性,我们可以非常容易的建立自己的扩展
using System; using Consul; using LZZ.DEV.WebServer.Models; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Hosting; namespace LZZ.DEV.WebServer { public static class AppBuilderExtensions { public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IApplicationLifetime lifetime, ServiceEntity serviceEntity) { var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{serviceEntity.ConsulIP}:{serviceEntity.ConsulPort}")); //请求注册的 Consul 地址 var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), // 服务启动多久后注册 Interval = TimeSpan.FromSeconds(10), // 健康检查时间间隔,或者称为心跳间隔 HTTP = $"http://{serviceEntity.IP}:{serviceEntity.Port}/api/health", // 健康检查地址 Timeout = TimeSpan.FromSeconds(5) // 超时时间 }; // Register service with consul var registration = new AgentServiceRegistration() { Checks = new[] {httpCheck}, ID = Guid.NewGuid().ToString(), Name = serviceEntity.ServiceName, Address = serviceEntity.IP, Port = serviceEntity.Port, Tags = new[] {$"urlprefix-/{serviceEntity.ServiceName}"} // 添加 urlprefix-/servicename 格式的 tag 标签,以便 Fabio 识别 }; consulClient.Agent.ServiceRegister(registration).Wait(); // 服务启动时注册,内部实现其实就是使用 Consul API 进行注册(HttpClient发起) lifetime.ApplicationStopping.Register(() => { consulClient.Agent.ServiceDeregister(registration.ID).Wait(); // 服务停止时取消注册 }); return app; } } }
当然,我们要使用consual,还需要安装consul依赖包
最后,我们在Startup.cs的Configure配置函数中,增加启动时注册本地条目到consual,完整代码如下
1 public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime) 2 { 3 app.UseMvc(routes => 4 { 5 routes.MapRoute( 6 name: "default", 7 template: "{controller=Home}/{action=Index}/{id?}"); 8 }); 9 10 var serviceEntity = new ServiceEntity 11 { 12 IP = "192.168.0.196", 13 Port = Convert.ToInt32(Configuration["Service:Port"]), 14 ServiceName = Configuration["Service:Name"], 15 ConsulIP = Configuration["Consul:IP"], 16 ConsulPort = Convert.ToInt32(Configuration["Consul:Port"]) 17 }; 18 app.RegisterConsul(lifetime, serviceEntity); 19 }
appsettings.json配置文件如下:
1 { 2 "Service": { 3 "Name": "LZZ.DEV.ClientService", 4 "Port": "5000" 5 }, 6 "Consul": { 7 "IP": "192.168.0.115", 8 "Port": "8500" 9 }, 10 "Logging": { 11 "LogLevel": { 12 "Default": "Warning" 13 } 14 }, 15 "AllowedHosts": "*" 16 }
好了,我们按下Ctrl+F5启动这个web应用程序瞧瞧。一切顺利,LZZ.DEV.WebServer已经被成功注册到consul中,使用相同方法也注册LZZ.PRO.WebServer到Consul中。
我们还可以通过http://192.168.153.129:8500/v1/catalog/service/LZZ.PRO.ClientService来访问consul注册这条服务的详细信息。
[ { "ID": "c612a043-8906-d6e1-8f4b-ef1c8afb371b", "Node": "consul-1", "Address": "192.168.153.129", "Datacenter": "dc1", "TaggedAddresses": { "lan": "192.168.153.129", "wan": "192.168.153.129" }, "NodeMeta": { "consul-network-segment": "" }, "ServiceKind": "", "ServiceID": "81d5b247-73d1-4ae5-9d1a-208770ca4e6a", "ServiceName": "LZZ.PRO.ClientService", "ServiceTags": [ "urlprefix-/LZZ.PRO.ClientService" ], "ServiceAddress": "192.168.153.132", "ServiceWeights": { "Passing": 1, "Warning": 1 }, "ServiceMeta": { }, "ServicePort": 5000, "ServiceEnableTagOverride": false, "ServiceProxyDestination": "", "ServiceProxy": { }, "ServiceConnect": { }, "CreateIndex": 2632, "ModifyIndex": 2632 } ]
关注ServiceAddress和ServicePort,即可完成对服务的调用。
总结
本篇主要介绍以最少化的集群创建了一个consul集群,具体各项细节都没深入研究,后续有时间我会慢慢深入,毕竟ASP.NET core天生就是一个做微服务的,感谢博客园的各位大神资料和参考。
参考
田园里的蟋蟀:《Docker & Consul & Fabio & ASP.NET Core 2.0 微服务跨平台实践》
感谢阅读!!