天天看點

.NET Core微服務之路:基于Consul最少叢集實作服務的注冊與發現(一)

Consul介紹

  Consul是HashiCorp公司推出的開源工具[開源位址:https://github.com/hashicorp/consul],用于實作分布式系統的服務發現與配置。

.NET Core微服務之路:基于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通,具體問題和配置可搜尋一下,圖檔如下:

.NET Core微服務之路:基于Consul最少叢集實作服務的注冊與發現(一)

  其中130作為leader角色,129和131作為follower角色,當然,在實際環境中,leader的角色不一定是固定的,會随着環境變化而變化(比如網絡斷了、當機了等等)這個我們後續來驗證。132和133作為用戶端,并安裝NET Core 2.1環境,再次提示,一定要保證在這個環境中的所有系統互相之間均能Ping通。

.NET Core微服務之路:基于Consul最少叢集實作服務的注冊與發現(一)

step1:關閉防火牆

systemctl stop firewalld
systemctl disable firewalld      

step2:安裝consul

.NET Core微服務之路:基于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微服務之路:基于Consul最少叢集實作服務的注冊與發現(一)

  接下來,我們建立一個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中。

.NET Core微服務之路:基于Consul最少叢集實作服務的注冊與發現(一)
.NET Core微服務之路:基于Consul最少叢集實作服務的注冊與發現(一)
.NET Core微服務之路:基于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 微服務跨平台實踐

感謝閱讀!!