.NET Core微服务之路:基于Consul最少集群实现服务的注册与发现(一)

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
简介: Consul介绍   Consul是HashiCorp公司推出的开源工具[开源地址:https://github.com/hashicorp/consul],用于实现分布式系统的服务发现与配置。     与市面上其他系统比较如下:     总体而言, Consul用Golang实现,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与Docker等轻量级容器可无缝配合。

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 微服务跨平台实践

 

感谢阅读!!

相关文章
|
2月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
126 3
|
2月前
|
Cloud Native Java API
聊聊从单体到微服务架构服务演化过程
本文介绍了从单体应用到微服务再到云原生架构的演进过程。单体应用虽易于搭建和部署,但难以局部更新;面向服务架构(SOA)通过模块化和服务总线提升了组件复用性和分布式部署能力;微服务则进一步实现了服务的独立开发与部署,提高了灵活性;云原生架构则利用容器化、微服务和自动化工具,实现了应用在动态环境中的弹性扩展与高效管理。这一演进体现了软件架构向着更灵活、更高效的方向发展。
|
2月前
|
Kubernetes 负载均衡 Docker
构建高效后端服务:微服务架构的探索与实践
【10月更文挑战第20天】 在数字化时代,后端服务的构建对于任何在线业务的成功至关重要。本文将深入探讨微服务架构的概念、优势以及如何在实际项目中有效实施。我们将从微服务的基本理念出发,逐步解析其在提高系统可维护性、扩展性和敏捷性方面的作用。通过实际案例分析,揭示微服务架构在不同场景下的应用策略和最佳实践。无论你是后端开发新手还是经验丰富的工程师,本文都将为你提供宝贵的见解和实用的指导。
|
2月前
|
监控 API 持续交付
构建高效后端服务:微服务架构的深度探索
【10月更文挑战第20天】 在数字化时代,后端服务的构建对于支撑复杂的业务逻辑和海量数据处理至关重要。本文深入探讨了微服务架构的核心理念、实施策略以及面临的挑战,旨在为开发者提供一套构建高效、可扩展后端服务的方法论。通过案例分析,揭示微服务如何帮助企业应对快速变化的业务需求,同时保持系统的稳定性和灵活性。
46 9
|
2月前
|
监控 安全 Java
构建高效后端服务:微服务架构深度解析与最佳实践###
【10月更文挑战第19天】 在数字化转型加速的今天,企业对后端服务的响应速度、可扩展性和灵活性提出了更高要求。本文探讨了微服务架构作为解决方案,通过分析传统单体架构面临的挑战,深入剖析微服务的核心优势、关键组件及设计原则。我们将从实际案例入手,揭示成功实施微服务的策略与常见陷阱,为开发者和企业提供可操作的指导建议。本文目的是帮助读者理解如何利用微服务架构提升后端服务的整体效能,实现业务快速迭代与创新。 ###
65 2
|
2月前
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
Android远程连接和登录FTPS服务代码(commons.net库)
28 1
|
2月前
|
消息中间件 Kafka 数据库
微服务架构中,如何确保服务之间的数据一致性?
微服务架构中,如何确保服务之间的数据一致性?
|
2月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
97 9
|
2月前
|
运维 Kubernetes 开发者
构建高效后端服务:微服务架构与容器化技术的结合
【10月更文挑战第18天】 在数字化转型的浪潮中,企业对后端服务的要求日益提高,追求更高的效率、更强的可伸缩性和更易于维护的系统。本文将探讨微服务架构与容器化技术如何结合,以构建一个既灵活又高效的后端服务体系。通过分析当前后端服务面临的挑战,介绍微服务和容器化的基本概念,以及它们如何相互配合来优化后端服务的性能和管理。本文旨在为开发者提供一种实现后端服务现代化的方法,从而帮助企业在竞争激烈的市场中脱颖而出。
28 0
|
3月前
|
消息中间件 Kafka 数据库
微服务架构中,如何确保服务之间的数据一致性
微服务架构中,如何确保服务之间的数据一致性