简介
Consul 是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,由 HashiCorp 公司用 Go 语言开发, 基于 Mozilla Public License 2.0 的协议进行开源. Consul 支持健康检查,并允许 HTTP 和 DNS 协议调用 API 存储键值对.
命令行超级好用的虚拟机管理软件 vgrant 也是 HashiCorp 公司开发的产品.
一致性协议采用 Raft 算法,用来保证服务的高可用. 使用 GOSSIP 协议管理成员和广播消息, 并且支持 ACL 访问控制.
什么是服务发现
微服务的框架体系中,服务发现是不能不提的一个模块。我相信了解或者熟悉微服务的童鞋应该都知道它的重要性。这里我只是简单的提一下,毕竟这不是我们的重点。我们看下面的一幅图片:
图中,客户端的一个接口,需要调用服务A-N。客户端必须要知道所有服务的网络位置的,以往的做法是配置是配置文件中,或者有些配置在数据库中。这里就带出几个问题:
- 需要配置N个服务的网络位置,加大配置的复杂性
- 服务的网络位置变化,都需要改变每个调用者的配置
- 集群的情况下,难以做负载(反向代理的方式除外)
既然有这些问题,那么服务发现就是解决这些问题的。话说,怎么解决呢?我们再看一张图
与之前一张不同的是,加了个服务发现模块。图比较简单,这边文字描述下。服务A-N把当前自己的网络位置注册到服务发现模块(这里注册的意思就是告诉),服务发现就以K-V的方式记录下,K一般是服务名,V就是IP:PORT。服务发现模块定时的轮询查看这些服务能不能访问的了(这就是健康检查)。客户端在调用服务A-N的时候,就跑去服务发现模块问下它们的网络位置,然后再调用它们的服务。这样的方式是不是就可以解决上面的问题了呢?客户端完全不需要记录这些服务网络位置,客户端和服务端完全解耦!
做服务发现的框架常用的有
- zookeeper
- eureka
- etcd
- consul
Consul 的使用场景
- docker 实例的注册与配置共享
- coreos 实例的注册与配置共享
- vitess 集群
- SaaS 应用的配置共享
- 与 confd服务集成,动态生成 nginx 和 haproxy 配置文件
使用
安装 Consul
1.wget https://dl.bintray.com/mitchellh/consul/0.4.1_linux_amd64.zip
2.unzip 0.4.1_linux_amd64.zip
3.sudo mv consul /bin
启动
consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node Litao-MacBook-Pro -dc sz-1
查看成员:
consul members
查看节点:
curl 127.0.0.1:8500/v1/catalog/nodes
使用DNS协议查看节点信息:
dig @127.0.0.1 -p 8600 Litao-MacBook-Pro.node.consul
注册服务
注册两个 Mysql 服务的实例, 数据中心在 sz-1, 端口都是 3306. 具体为以下命令:
curl -X PUT -d '{"Datacenter": "sz-1", "Node": "mysql-1", "Address": \
"mysql-1.node.consul","Service": {"Service": "mysql", "tags": ["master","v1"], \
"Port": 3306}}' http://127.0.0.1:8500/v1/catalog/register
curl -X PUT -d '{"Datacenter": "sz-1", "Node": "mysql-2", "Address": \
"mysql-2.node.consul","Service": {"Service": "mysql", "tags": ["slave","v1"],\
"Port": 3306}}' http://127.0.0.1:8500/v1/catalog/register
curl http://127.0.0.1:8500/v1/catalog/service/mysql
[
{
"Address": "mysql-1.node.consul",
"Node": "mysql-1",
"ServiceID": "mysql",
"ServiceName": "mysql",
"ServicePort": 3306,
"ServiceTags": [
"master",
"v1"
]
},
{
"Address": "mysql-2.node.consul",
"Node": "mysql-2",
"ServiceID": "mysql",
"ServiceName": "mysql",
"ServicePort": 3306,
"ServiceTags": [
"slave",
"v1"
]
}
]
dig @127.0.0.1 -p 8600 mysql.service.consul SRV
[
{
"Address": "mysql-1.node.consul",
"Node": "mysql-1",
"ServiceID": "mysql",
"ServiceName": "mysql",
"ServicePort": 3306,
"ServiceTags": [
"master",
"v1"
]
},
{
"Address": "mysql-2.node.consul",
"Node": "mysql-2",
"ServiceID": "mysql",
"ServiceName": "mysql",
"ServicePort": 3306,
"ServiceTags": [
"slave",
"v1"
]
}
]
dig @127.0.0.1 -p 8600 mysql.service.consul SRV
; <<>> DiG 9.10.0-P2 <<>> @127.0.0.1 -p 8600 mysql.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12821
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;mysql.service.consul. IN SRV
;; ANSWER SECTION:
mysql.service.consul. 0 IN SRV 1 1 3306 mysql-2.node.sz-1.consul.
mysql.service.consul. 0 IN SRV 1 1 3306 mysql-1.node.sz-1.consul.
;; ADDITIONAL SECTION:
mysql-2.node.sz-1.consul. 0 IN CNAME mysql-2.node.consul.
mysql-1.node.sz-1.consul. 0 IN CNAME mysql-1.node.consul.
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Tue Dec 02 16:42:38 CST 2014
;; MSG SIZE rcvd: 280