Jusene's Blog

Consul 微服务之服务发现和配置共享

字数统计: 3.4k阅读时长: 19 min
2017/11/08 Share

Consul

微服务的框架体系中,服务发现是不能不提的一个模块,传统的服务框架必须知道服务的网络位置,而这些位置信息都是通过配置文件完成,当服务大量扩张的时候,这管理规模别提多么庞大,更别提现在的docker容器化的大量部署的时代,如何可以动态的让程序间明白我所需要的服务在哪?是微服务时代必须解决的事情,而随着微服务越来越流行,大量涌现的服务发现框架,我们比较常见的用:zookeeper,eureka,etcd,consul……

存在即合理,多种服务发现框架也都有自己的适用地方,而这里之所以我学习consul,就是项目上使用了consul。

consul是分布式的、高可用的、横向扩展的,consul提供了一些关键特性:

  • 服务发现:consul通过DNS或者HTTP接口使服务注册和服务发现的很容易。
  • 健康检查:健康检查使consul可以快速告警集群中的操作。和服务发现的集成,可以防止服务转发到故障服务上。
  • K/V存储:一个用来存储动态配置的系统,提供简单的HTTP接口,可以在任何地方操作。
  • 多数据中心:无需任何配置即可支持任意的区域。

从图上发现,consul的集群是由多个client和server组成的。而不管server还是client,都是consul的一个节点,我们都可以将服务注册上任意节点。

  • client
    client表示consul的client模式,在这个模式下注册的服务会被转发到server,本身不会持久化这些信息。

  • server
    server表示consul的server模式,这个模式下,基本功能都和client一样,唯一不同的是,它会把所有的信息持久化到本地。

  • server-leader
    顾名思义,这是server模式的leader,它除了普通server的功能外,还需要负责同步注册的信息给其他的server,同时也要负责各个节点的健康监测。

Start Consul

Consul的安装十分简单,可以到官网直接下载:https://www.consul.io/downloads.html

1
~]# consul agent -server -data-dir=/tmp/consul -bootstrap-expect 1 -node server -bind=10.211.55.6
2
BootstrapExpect is set to 1; this is the same as Bootstrap mode.
3
bootstrap = true: do not enable unless necessary
4
==> Starting Consul agent...
5
==> Consul agent running!
6
           Version: 'v1.0.0'
7
           Node ID: '0c99b5a9-f603-9fa6-fcf3-9703e07ffb24'
8
         Node name: 'server'
9
        Datacenter: 'dc1' (Segment: '<all>')
10
            Server: true (Bootstrap: true)
11
       Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, DNS: 8600)
12
      Cluster Addr: 10.211.55.6 (LAN: 8301, WAN: 8302)
13
           Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false
14
15
==> Log data will now stream in as it occurs:
16
17
    2017/10/27 13:14:05 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:0c99b5a9-f603-9fa6-fcf3-9703e07ffb24 Address:10.211.55.6:8300}]
18
    2017/10/27 13:14:05 [INFO] raft: Node at 10.211.55.6:8300 [Follower] entering Follower state (Leader: "")
19
    2017/10/27 13:14:05 [INFO] serf: EventMemberJoin: server.dc1 10.211.55.6
20
    2017/10/27 13:14:05 [INFO] serf: EventMemberJoin: server 10.211.55.6
21
    2017/10/27 13:14:05 [INFO] consul: Adding LAN server server (Addr: tcp/10.211.55.6:8300) (DC: dc1)
22
    2017/10/27 13:14:05 [INFO] agent: Started DNS server 127.0.0.1:8600 (udp)
23
    2017/10/27 13:14:05 [INFO] consul: Handled member-join event for server "server.dc1" in area "wan"
24
    2017/10/27 13:14:05 [INFO] agent: Started DNS server 127.0.0.1:8600 (tcp)
25
    2017/10/27 13:14:05 [INFO] agent: Started HTTP server on 127.0.0.1:8500 (tcp)
26
    2017/10/27 13:14:10 [WARN] raft: Heartbeat timeout from "" reached, starting election
27
    2017/10/27 13:14:10 [INFO] raft: Node at 10.211.55.6:8300 [Candidate] entering Candidate state in term 2
28
    2017/10/27 13:14:10 [INFO] raft: Election won. Tally: 1
29
    2017/10/27 13:14:10 [INFO] raft: Node at 10.211.55.6:8300 [Leader] entering Leader state
30
    2017/10/27 13:14:10 [INFO] consul: cluster leadership acquired
31
    2017/10/27 13:14:10 [INFO] consul: New leader elected: server
32
    2017/10/27 13:14:10 [INFO] consul: member 'server' joined, marking health alive
33
    2017/10/27 13:14:11 [INFO] agent: Synced node info
34
35
~]# consul members
36
Node    Address           Status  Type    Build  Protocol  DC   Segment
37
server  10.211.55.6:8301  alive   server  1.0.0  2         dc1  <all>
38
39
~]# curl 127.0.0.1:8500/v1/catalog/nodes
40
[{"ID":"0c99b5a9-f603-9fa6-fcf3-9703e07ffb24","Node":"server","Address":"10.211.55.6","Datacenter":"dc1","TaggedAddresses":{"lan":"10.211.55.6","wan":"10.211.55.6"},"Meta":{"consul-network-segment":""},"CreateIndex":5,"ModifyIndex":6}]
41
42
~]# dig @127.0.0.1 -p 8600 server.node.consul
43
44
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 server.node.consul
45
; (1 server found)
46
;; global options: +cmd
47
;; Got answer:
48
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44902
49
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
50
;; WARNING: recursion requested but not available
51
52
;; OPT PSEUDOSECTION:
53
; EDNS: version: 0, flags:; udp: 4096
54
;; QUESTION SECTION:
55
;server.node.consul.            IN      A
56
57
;; ANSWER SECTION:
58
server.node.consul.     0       IN      A       10.211.55.6
59
60
;; Query time: 0 msec
61
;; SERVER: 127.0.0.1#8600(127.0.0.1)
62
;; WHEN: Fri Oct 27 13:19:51 EDT 2017
63
;; MSG SIZE  rcvd: 63

Register Service

服务发现的前提是我们需要注册直接的服务,现在我们来注册自己的服务。

1
~]# mkdir /etc/consul.d
2
~]# cat > /etc/consul.d/web.json << EOF
3
{
4
	"service": {
5
		"name": "web", 
6
		"tags": ["Django"], 
7
		"port": 80
8
	}
9
}
10
EOF
11
~]# consul agent -server -data-dir=/tmp/consul -bootstrap-expect 1 -node server -bind=10.211.55.6 -config-dir=/etc/consul.d/
12
BootstrapExpect is set to 1; this is the same as Bootstrap mode.
13
bootstrap = true: do not enable unless necessary
14
==> Starting Consul agent...
15
==> Consul agent running!
16
           Version: 'v1.0.0'
17
           Node ID: '0c99b5a9-f603-9fa6-fcf3-9703e07ffb24'
18
         Node name: 'server'
19
        Datacenter: 'dc1' (Segment: '<all>')
20
            Server: true (Bootstrap: true)
21
       Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, DNS: 8600)
22
      Cluster Addr: 10.211.55.6 (LAN: 8301, WAN: 8302)
23
           Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false
24
25
==> Log data will now stream in as it occurs:
26
27
    2017/10/27 13:32:26 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:0c99b5a9-f603-9fa6-fcf3-9703e07ffb24 Address:10.211.55.6:8300}]
28
    2017/10/27 13:32:26 [INFO] raft: Node at 10.211.55.6:8300 [Follower] entering Follower state (Leader: "")
29
    2017/10/27 13:32:26 [INFO] serf: EventMemberJoin: server.dc1 10.211.55.6
30
    2017/10/27 13:32:26 [WARN] serf: Failed to re-join any previously known node
31
    2017/10/27 13:32:26 [INFO] serf: EventMemberJoin: server 10.211.55.6
32
    2017/10/27 13:32:26 [INFO] agent: Started DNS server 127.0.0.1:8600 (udp)
33
    2017/10/27 13:32:26 [INFO] consul: Handled member-join event for server "server.dc1" in area "wan"
34
    2017/10/27 13:32:26 [WARN] serf: Failed to re-join any previously known node
35
    2017/10/27 13:32:26 [INFO] consul: Adding LAN server server (Addr: tcp/10.211.55.6:8300) (DC: dc1)
36
    2017/10/27 13:32:26 [INFO] agent: Started DNS server 127.0.0.1:8600 (tcp)
37
    2017/10/27 13:32:26 [INFO] agent: Started HTTP server on 127.0.0.1:8500 (tcp)
38
    2017/10/27 13:32:33 [ERR] agent: failed to sync remote state: No cluster leader
39
    2017/10/27 13:32:35 [WARN] raft: Heartbeat timeout from "" reached, starting election
40
    2017/10/27 13:32:35 [INFO] raft: Node at 10.211.55.6:8300 [Candidate] entering Candidate state in term 3
41
    2017/10/27 13:32:35 [INFO] raft: Election won. Tally: 1
42
    2017/10/27 13:32:35 [INFO] raft: Node at 10.211.55.6:8300 [Leader] entering Leader state
43
    2017/10/27 13:32:35 [INFO] consul: cluster leadership acquired
44
    2017/10/27 13:32:35 [INFO] consul: New leader elected: server
45
    2017/10/27 13:32:37 [INFO] agent: Synced service 'web'
46
47
~]# curl http://127.0.0.1:8500/v1/catalog/service/web
48
[{"ID":"0c99b5a9-f603-9fa6-fcf3-9703e07ffb24","Node":"server","Address":"10.211.55.6","Datacenter":"dc1","TaggedAddresses":{"lan":"10.211.55.6","wan":"10.211.55.6"},"NodeMeta":{"consul-network-segment":""},"ServiceID":"web","ServiceName":"web","ServiceTags":["Django"],"ServiceAddress":"","ServicePort":80,"ServiceEnableTagOverride":false,"CreateIndex":61,"ModifyIndex":61}]
49
50
~]# curl http://127.0.0.1:8500/v1/catalog/service/web?passing   #健康状态检查
51
[{"ID":"0c99b5a9-f603-9fa6-fcf3-9703e07ffb24","Node":"server","Address":"10.211.55.6","Datacenter":"dc1","TaggedAddresses":{"lan":"10.211.55.6","wan":"10.211.55.6"},"NodeMeta":{"consul-network-segment":""},"ServiceID":"web","ServiceName":"web","ServiceTags":["Django"],"ServiceAddress":"","ServicePort":80,"ServiceEnableTagOverride":false,"CreateIndex":61,"ModifyIndex":61}]
52
53
~]# dig @127.0.0.1 -p 8600 web.service.consul
54
55
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 web.service.consul
56
; (1 server found)
57
;; global options: +cmd
58
;; Got answer:
59
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21835
60
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
61
;; WARNING: recursion requested but not available
62
63
;; OPT PSEUDOSECTION:
64
; EDNS: version: 0, flags:; udp: 4096
65
;; QUESTION SECTION:
66
;web.service.consul.            IN      A
67
68
;; ANSWER SECTION:
69
web.service.consul.     0       IN      A       10.211.55.6
70
71
;; Query time: 0 msec
72
;; SERVER: 127.0.0.1#8600(127.0.0.1)
73
;; WHEN: Fri Oct 27 13:38:07 EDT 2017
74
;; MSG SIZE  rcvd: 63
75
76
~]# dig @127.0.0.1 -p 8600 Django.web.service.consul
77
78
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 Django.web.service.consul
79
; (1 server found)
80
;; global options: +cmd
81
;; Got answer:
82
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43935
83
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
84
;; WARNING: recursion requested but not available
85
86
;; OPT PSEUDOSECTION:
87
; EDNS: version: 0, flags:; udp: 4096
88
;; QUESTION SECTION:
89
;Django.web.service.consul.     IN      A
90
91
;; ANSWER SECTION:
92
Django.web.service.consul. 0    IN      A       10.211.55.6
93
94
;; Query time: 0 msec
95
;; SERVER: 127.0.0.1#8600(127.0.0.1)
96
;; WHEN: Fri Oct 27 13:38:38 EDT 2017
97
;; MSG SIZE  rcvd: 70

Consul Cluster

新起一台client consul:

1
~]# consul agent -data-dir=/tmp/consul -node=client -bind=10.211.55.43
2
==> Starting Consul agent...
3
==> Consul agent running!
4
           Version: 'v1.0.0'
5
           Node ID: 'd008bc60-ed76-1feb-3ed5-372e81fc35ef'
6
         Node name: 'client'
7
        Datacenter: 'dc1' (Segment: '')
8
            Server: false (Bootstrap: false)
9
       Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, DNS: 8600)
10
      Cluster Addr: 10.211.55.43 (LAN: 8301, WAN: 8302)
11
           Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false
12
13
==> Log data will now stream in as it occurs:
14
15
    2017/08/13 02:27:34 [INFO] serf: EventMemberJoin: client 10.211.55.43
16
    2017/08/13 02:27:34 [INFO] agent: Started DNS server 127.0.0.1:8600 (udp)
17
    2017/08/13 02:27:34 [INFO] agent: Started DNS server 127.0.0.1:8600 (tcp)
18
    2017/08/13 02:27:34 [INFO] agent: Started HTTP server on 127.0.0.1:8500 (tcp)
19
    2017/08/13 02:27:34 [WARN] manager: No servers available
20
    2017/08/13 02:27:34 [ERR] agent: failed to sync remote state: No known Consul servers
21
22
~]# consul  join 10.211.55.6
23
Successfully joined cluster by contacting 1 nodes.
24
25
~]#  consul members
26
Node    Address            Status  Type    Build  Protocol  DC   Segment
27
server  10.211.55.6:8301   alive   server  1.0.0  2         dc1  <all>
28
client  10.211.55.43:8301  alive   client  1.0.0  2         dc1  <default>
29
30
~]#  dig @127.0.0.1 -p 8600 web.service.consul   #服务同步
31
32
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7 <<>> @127.0.0.1 -p 8600 web.service.consul
33
; (1 server found)
34
;; global options: +cmd
35
;; Got answer:
36
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50027
37
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
38
;; WARNING: recursion requested but not available
39
40
;; OPT PSEUDOSECTION:
41
; EDNS: version: 0, flags:; udp: 4096
42
;; QUESTION SECTION:
43
;web.service.consul.            IN      A
44
45
;; ANSWER SECTION:
46
web.service.consul.     0       IN      A       10.211.55.6
47
48
;; Query time: 5 msec
49
;; SERVER: 127.0.0.1#8600(127.0.0.1)
50
;; WHEN: Sun Aug 13 02:33:25 CST 2017
51
;; MSG SIZE  rcvd: 63

Health Check

定义health check,检查内容只针对单节点的服务。

1
~]# cat > /etc/consul.d/ping.json << EOF
2
{"check": {"name": "ping","script": "ping -c1 google.com >/dev/null", "interval": "30s"}}
3
EOF
4
~]# cat > /etc/consul.d/web1.json << EOF
5
{"service": {"name": "web", "tags": ["rails"], "port": 80,"check": {"script": "curl localhost >/dev/null 2>&1", "interval": "10s"}}}
6
EOF
7
8
~]# consul agent -data-dir=/tmp/consul -node=client -bind=10.211.55.43 -config-dir=/etc/consul.d/ -enable-script-checks=true
9
....
10
    2017/08/13 02:43:08 [INFO] agent: Synced service 'web'
11
    2017/08/13 02:43:08 [INFO] agent: Synced check 'ping'
12
    2017/08/13 02:43:18 [WARN] agent: Check 'ping' is now warning
13
    2017/08/13 02:43:18 [INFO] agent: Synced check 'ping'
14
    2017/08/13 02:43:58 [WARN] agent: Check 'ping' is now warning
15
    2017/08/13 02:44:11 [WARN] agent: Check 'service:web' is now critical
16
    2017/08/13 02:44:11 [INFO] agent: Synced check 'service:web'
17
    2017/08/13 02:44:21 [WARN] agent: Check 'service:web' is now critical
18
    2017/08/13 02:44:31 [WARN] agent: Check 'service:web' is now critical
19
20
~]# curl http://127.0.0.1:8500/v1/health/state/critical
21
[{"Node":"client","CheckID":"service:web","Name":"Service 'web' check","Status":"critical","Notes":"","Output":"","ServiceID":"web","ServiceName":"web","ServiceTags":["rails"],"CreateIndex":174,"ModifyIndex":204}]

k/v存储

consul也是一个k/v数据库,这样我们就可以实现配置共享。

client

1
~]# consul kv put redis/config/port 6666
2
Success! Data written to: redis/config/port

server

1
~]# consul kv get redis/config/port 
2
6666
3
~]# consul kv get -detailed redis/config/port  获取详细信息
4
CreateIndex      281
5
Flags            0
6
Key              redis/config/port
7
LockIndex        0
8
ModifyIndex      281
9
Session          -
10
Value            6666
11
~]# consul kv get -recurse
12
redis/config/port:6666

check-and-set

1
$ consul kv put -cas -modify-index=123 foo bar
2
Success! Data written to: foo
3
4
$ consul kv put -cas -modify-index=123 foo bar
5
Error! Did not write to foo: CAS failed

delete

1
~]# consul kv delete redis/config/port
2
Success! Deleted key: redis/config/port
3
~]# consul kv delete -recurse redis        #递归删除
4
Success! Deleted keys with prefix: redis

Web UI

1
~]# consul agent -server -data-dir=/tmp/consul -bootstrap-expect 1 -node server -bind=10.211.55.6 -ui

CATALOG
  1. 1. Consul
  2. 2. Start Consul
  3. 3. Register Service
  4. 4. Consul Cluster
  5. 5. Health Check
  6. 6. k/v存储
  7. 7. Web UI