consul分布式集群搭建


環境准備

三台機器:

vm-a    10.200.110.90    centos7
vm-b    10.200.110.91    centos7
vm-c    10.200.110.93    centos7
Consul官網(https://www.consul.io/downloads.html)下載相應系統的consul可執行文件並放系統PATH環境變量目錄內。

我下載的是consul_1.4.3_linux_amd64.zip,在上面的每台機器上解壓,並拷貝到/usr/local/bin目錄下。

unzip consul_1.4.3_linux_amd64.zip
mv cosul /usr/local/bin

 集群啟動

10.200.110.90啟動consul
consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=10.200.110.90 -bind=10.200.110.90 -client=0.0.0.0 -datacenter=shenzhen -ui
10.200.110.91啟動consul
consul agent -server -bootstrap-expect 3 -data-dir /tmp/consul -node 10.200.110.91 -bind=10.200.110.91 -client=0.0.0.0 -datacenter shenzhen -ui
10.200.110.93啟動consul
consul agent -server -bootstrap-expect 3 -data-dir /tmp/consul -node 10.200.110.93 -bind=10.200.110.93 -client=0.0.0.0 -datacenter shenzhen -ui

參數說明:

  •  server: 以server身份啟動。默認是client
  •  bootstrap-expect:集群要求的最少server數量,當低於這個數量,集群即失效。
  •  data-dir:data存放的目錄,更多信息請參閱consul數據同步機制
  •  node:節點id,集群中的每個node必須有一個唯一的名稱。默認情況下,Consul使用機器的hostname
  •  bind:監聽的ip地址。默認綁定0.0.0.0,可以不指定。表示Consul監聽的地址,而且它必須能夠被集群中的其他節點訪問。Consul默認會監聽第一個private IP,但最好還是提供一個。生產設備上的服務器通常有好幾個網卡,所以指定一個不會出錯
  •  client: 客戶端的ip地址,0.0.0.0是指誰都可以訪問(不加這個,下面的ui :8500無法訪問)
  •  ui: 可以訪問UI界面
  • -config-dir指定配置文件夾,Consul會加載其中的所有文件
  • -datacenter 指定數據中心名稱,默認是dc1

此時三台機器都會打印:

    2019/03/20 10:57:36 [INFO] agent: Started HTTP server on 127.0.0.1:8500 (tcp)
    2019/03/20 10:57:36 [INFO] agent: started state syncer
    2019/03/20 10:57:44 [ERR] agent: failed to sync remote state: No cluster leader

此時三台機器還未join,不能算是一個集群,三台機器上的consul均不能正常工作,因為leader未選出。


三台機器組成consul集群

consul集群:當一個consul agent啟動后,它不知道任何其他節點,要學習到集群中的其他節點,agent必須加入一個已經存在的集群(cluster)。要加入這樣的集群,它只需要知道這個集群中的一個節點即可。它加入后,將會和這個member gossip(交談)並迅速發現集群中的其他節點。一個consul agent可以加入任何類型的其他agent,而不只是那些運行於server mode的agent。

分別登錄第2台和第3台虛擬機上執行如下命令,讓consul加入集群:
10.200.110.91加入10.200.110.90

[root@localhost consul-cluster]# consul join 10.200.110.90
Successfully joined cluster by contacting 1 nodes.
[root@localhost consul-cluster]#

10.200.110.93加入10.200.110.90

[root@localhost consul-cluster]# consul join 10.200.110.90
Successfully joined cluster by contacting 1 nodes. [root@localhost consul-cluster]#

很快三台機器都會打印:

    2019/03/20 10:59:12 [INFO] raft: Added peer d89335fd-cfb8-1fc0-3902-b847e125fa2c, starting replication
    2019/03/20 10:59:12 [INFO] consul: cluster leadership acquired
    2019/03/20 10:59:12 [INFO] consul: New leader elected: 10.200.110.90

證明此時leader已經選出,集群可以正常工作。訪問:http://10.200.110.90:8500/

上圖中的下拉框是datacenter的選項。


集群狀態查看

[root@localhost ~]# consul operator raft list-peers
Node           ID                                    Address             State     Voter  RaftProtocol
10.200.110.90  239bfd6a-28d0-094a-4d93-09bf81414528  10.200.110.90:8300  leader    true   3
10.200.110.91  d1b05900-4f8f-b956-5ba6-5a3c798d93d3  10.200.110.91:8300  follower  true   3
10.200.110.93  d89335fd-cfb8-1fc0-3902-b847e125fa2c  10.200.110.93:8300  follower  true   3
[root@localhost ~]# 

查看members狀態:

[root@localhost ~]# consul members
Node           Address             Status  Type    Build  Protocol  DC        Segment
10.200.110.90  10.200.110.90:8301  alive   server  1.4.3  2         shenzhen  <all>
10.200.110.91  10.200.110.91:8301  alive   server  1.4.3  2         shenzhen  <all>
10.200.110.93  10.200.110.93:8301  alive   server  1.4.3  2         shenzhen  <all>
[root@localhost ~]# 

集群參數get/set測試

10.200.110.93的set操作:

[root@localhost ~]# consul kv put addr nanshan
Success! Data written to: addr
[root@localhost ~]#

10.200.110.91的get操作:

[root@localhost consul-cluster]# consul kv get addr
nanshan
[root@localhost consul-cluster]#

在10.200.110.90可以正常設置key的值為value,並能正常查回來。三台機器獲取key的值均為value,如此可知key的值已經在集群中同步。


集群單機故障處理

單機consul進程故障發生
殺死三台機器中任意一台機器上的consul進程,這里殺死leader 192.168.1.235

10.200.110.90機器上執行:

[root@localhost ~]# ps -ef | grep consul
root      24811   7330  6 10:57 pts/0    00:12:44 consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=10.200.110.90 -bind=10.200.110.90 -datacenter=shenzhen -ui
root      24957  24939  0 13:59 pts/1    00:00:00 grep --color=auto consul
[root@localhost ~]# kill -9 24811
[root@localhost ~]# 

此時看此台機器上的consul的log:

    2019/03/20 11:03:36 [INFO] serf: EventMemberUpdate: 10.200.110.93.shenzhen
    2019/03/20 11:03:37 [WARN] raft: Failed to contact d89335fd-cfb8-1fc0-3902-b847e125fa2c in 2.500740308s
    2019/03/20 11:03:37 [INFO] raft: pipelining replication to peer {Voter d89335fd-cfb8-1fc0-3902-b847e125fa2c 10.200.110.93:8300}
已殺死
[root@localhost consul-cluster]# 

Consul進程已經在這台機器上退出。
此時都會10.200.110.9110.200.110.93都會打印

[ERR] agent: failed to sync remote state:No cluster leader

[WARN] raft: Heartbeat timeout from"10.200.110.90:8300" reached, starting election

Leader丟失,剩下的兩台機重新進行leader選舉

[root@localhost ~]# consul operator raft list-peers
Node           ID                                    Address             State     Voter  RaftProtocol
10.200.110.93  d89335fd-cfb8-1fc0-3902-b847e125fa2c  10.200.110.93:8300  leader    true   3
10.200.110.91  d1b05900-4f8f-b956-5ba6-5a3c798d93d3  10.200.110.91:8300  follower  true   3
10.200.110.90  239bfd6a-28d0-094a-4d93-09bf81414528  10.200.110.90:8300  follower  true   3
[root@localhost ~]#

此時再對10.200.110.91和10.200.110.93進行key的get/set操作:

[root@localhost ~]# consul kv get addr
nanshan
[root@localhost ~]# 

均能正常get到key的值為nanshan。

Consul 多數據中心配置 MULTIPLE DATACENTERS

在consul集群中,多數據中心可以進行配置:
LAN gossip pool包含了同一局域網內所有節點,包括server與client。這基本上是位於同一個數據中心DC。
WAN gossip pool一般僅包含server,將跨越多個DC數據中心,通過互聯網或廣域網進行通信。
我們之前講過的啟動集群命令使用的是-bootstrap 來作為服務的啟動:

10.200.110.95啟動consul
consul agent -server -bootstrap-expect 3 -data-dir /tmp/consul -node 10.200.110.95 -bind=10.200.110.93 -datacenter guangzhou -ui

查詢當前集群下擁有的datacenter信息:
consul members -wan

我這里有兩個數據中心shenzhen和guangzhou,使用下面的命令將數據中心互相可見:

[root@localhost ~]# consul join -wan 10.200.110.91
Successfully joined cluster by contacting 1 nodes.
[root@localhost ~]#

多數據中心就配好了,在之前的UI中也可以看到了:

查詢當前集群下擁有的datacenter信息:

[root@localhost ~]# consul members -wan
Node                     Address             Status  Type    Build  Protocol  DC         Segment
10.200.110.91.shenzhen   10.200.110.91:8302  alive   server  1.4.3  2         shenzhen   <all>
10.200.110.93.shenzhen   10.200.110.93:8302  alive   server  1.4.3  2         shenzhen   <all>
10.200.110.95.guangzhou  10.200.110.95:8302  alive   server  1.4.3  2         guangzhou  <all>
[root@localhost ~]#

 參照consul部署,部署兩個數據中dc1和dc2。數據中心的名字對consul而言是不透明的,它們只是用於管理員與consul交互使用。

        通過consulmembers –wan命令可以查詢WAN中的節點:

$ consul members-wan
...
        輸出結果是WAN gossip pool中的節點列表,只包含server節點。 client節點只會想本地數據中的server節點發送請求,不會加入WAN Gossip Pool。Client請求會通過本地數據中的Server節點轉發到目標數據中心。

        下一步是保證所有的Server節點均加入到WAN gossip Pool。

$ consul join -wan<server 1> <server 2> ...
...
        join命令加上-wan參數,是講Server加入到WAN gossip pool。而LAN gossip pool,只需要加入到現有的某個Server節點即可,和通過gossip協議與其他成員交換信息即可知道所有的成員節點。然而,對於啟動的consul的Server,只知道自己的信息,必須添加到群集中。

        一旦加入完成,基於WAN通過gossip協議就可以使用members命令查詢所有的Server節點。

        我們也可以通過HTTP API來查詢所有的數據中心:

$ curlhttp://localhost:8500/v1/catalog/datacenters
["dc1", "dc2"]
        做一個簡單的測試,查詢某個數據中心的所有節點:

$ curlhttp://localhost:8500/v1/catalog/nodes?dc=dc1
...
$ curlhttp://localhost:8500/v1/catalog/nodes?dc=dc2
...
        構建多數據中心,網絡需要滿足如下要求:1.所有的Server節點都是互通,否則,基於gossip協議的RPC轉發將無法工作。如果服務發現是可以跨數據中心,網絡必須能夠跨區域之間的路由的IP地址以及。2.如果使用服務發現,那么所有的數據中心都是互通的,或者基於VPN或其他隧道機制是互通的。Consul不能處理VPN、address rewritting,或者NAT traversal。

SpringCloud在consul集群示例

環境:

ip 10.200.110.90 10.200.110.91 10.200.110.93 10.200.110.89 10.200.110.95
consul agent consul agent server consul agent server consul agent server    
app service-consumer     service-consumer  
app         service-producter
app          

應用注冊consul為:

應用啟動時注冊到consul集群的命令行:

java -jar -Dspring.cloud.consul.host=10.200.110.91 -Dserver.port=8091 -Dspring.cloud.consul.discovery.hostname=10.200.110.90 service-consumer-201903201556.jar

 

現在測試consul集群的高可用性,將10.200.110.90的consul agent server停掉。

service-consumer:

service-producter:

再觸發一次service-consumer調用service-producter的測試,訪問10.200.110.90:8091,調用到了10.200.110.95:8081的應用上。

http://10.200.110.90:8091/swagger-ui.html#!/book-consumer/getbook5UsingGET

 

consul的服務注冊的兩種方式:

和《Consul之:服務注冊與發現》有些重復。

方式1:通過配置文件方式

通過在consul的服務器的工作目錄中增加consul的配置文件的方式進行服務注冊,

例如,我在consul的機器上的/home/consul-cluster/config增加如下配置文件:

{
    "service":
    {
        "name": "service-front",
        "tags": ["jar"],
        "address": "10.200.110.97",
        "port": 8001,
        "checks": [
        {
            "http": "http://10.200.110.97:8001/health",
            "interval": "10s"
        }]
    }
}

 如果有多個服務時,

{
    "services": [{
        "id":"front1",
        "name": "service-front",
        "tags": ["local-dev"],
        "address": "10.200.110.100",
        "port": 8001,
        "checks": [{
            "http": "http://10.200.110.100:8001/health",
            "interval": "10s"
        }]
    },
     {
        "id":"front2",
        "name": "service-front",
        "tags": ["jar"],
        "address": "10.200.110.97",
        "port": 8001,
        "checks": [{
            "http": "http://10.200.110.97:8001/health",
            "interval": "10s"
        }]
    }]
}

在consul的控制台上,可見服務注冊成功。如下:

或者通過命令行查看驗證服務是否注冊成功:

[root@localhost consul-template]# curl http://10.200.110.90:8500/v1/catalog/service/service-front
[{"ID":"d1b05900-4f8f-b956-5ba6-5a3c798d93d3","Node":"10.200.110.91","Address":"10.200.110.91","Datacenter":"shenzhen","TaggedAddresses":{"lan":"10.200.110.91","wan":"10.200.110.91"},"NodeMeta":{"consul-network-segment":""},"ServiceKind":"","ServiceID":"service-front-10-200-110-100-8001","ServiceName":"service-front","ServiceTags":["front-dev,這是個前置應用,網關層","duan"],"ServiceAddress":"10.200.110.100","ServiceWeights":{"Passing":1,"Warning":1},"ServiceMeta":{},"ServicePort":8001,"ServiceEnableTagOverride":false,"ServiceProxyDestination":"","ServiceProxy":{},"ServiceConnect":{},"CreateIndex":11382,"ModifyIndex":11382},{"ID":"382f88c2-4482-e1f7-1453-28f94ff65108","Node":"10.200.110.97","Address":"10.200.110.97","Datacenter":"shenzhen","TaggedAddresses":{"lan":"10.200.110.97","wan":"10.200.110.97"},"NodeMeta":{"consul-network-segment":""},"ServiceKind":"","ServiceID":"front1","ServiceName":"service-front","ServiceTags":["local-dev"],"ServiceAddress":"","ServiceWeights":{"Passing":1,"Warning":1},"ServiceMeta":{},"ServicePort":8001,"ServiceEnableTagOverride":false,"ServiceProxyDestination":"","ServiceProxy":{},"ServiceConnect":{},"CreateIndex":11976,"ModifyIndex":11976}][root@localhost consul-template]#

 

方式2:通過consul api方式

spring.cloud.consul.discovery.enabled: true
spring.cloud.consul.discovery.healthCheckInterval: 10s
spring.cloud.consul.discovery.instanceId: ${spring.application.name}:${spring.cloud.consul.discovery.hostname}:${server.port}
spring.cloud.consul.enabled: true
spring.cloud.consul.host: 10.200.110.100
spring.cloud.consul.port: 8500
spring.zipkin.base-url: http://10.200.110.4:9411

management.security.enabled: false 

server:
  port: 8001
spring:
  application:
    name: service-front
    author: duanxz
    description: service-front
  cloud:
    consul:
      discovery:
        hostname: 127.0.0.1
        tags:
        - front-dev,這是個前置應用,網關層
        - duan

 

待解決的問題

我組成的2個服務:

[root@localhost config]# cat apps.json 

{
    "services": [{
        "id":"front1",
        "name": "service-front",
        "tags": ["local-dev"],
        "port": 8001,
        "checks": [{
            "http": "http://10.200.110.97:8001/health",
            "interval": "10s"
        }]
    },
     {
        "id":"demo",
        "name": "service-demo",
        "tags": ["jar"],
        "address": "10.200.110.97",
        "port": 8071,
        "checks": [{
            "http": "http://10.200.110.97:8071/health",
            "interval": "10s"
        }]
    }]
}
[root@localhost config]#

 

通過json配置文件的方式,注冊到consul上的服務間無法通過Feign調用,

我的demo里,是service-front調用service-demo,打開swagger調用出現如下錯誤:

{
  "timestamp": 1553161721543,
  "status": 500,
  "error": "Internal Server Error",
  "exception": "java.lang.RuntimeException",
  "message": "Request processing failed; nested exception is java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: service-demo",
  "path": "/book/show6/1"
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM