背景
本文并不介绍服务发现的基本原理。除了一致性算法之外,其他并没有太多高深的算法,网上的资料很容易让大家明白上面是服务发现。
想直接查看结论的同学,请直接跳到文末。
目前,市面上有非常多的服务发现工具,《Open-Source Service Discovery》(http://jasonwilder.com/blog/2014/02/04/service-discovery-in-the-cloud/)一文中列举了如下开源的服务发现工具。
Zookeeper | General | CP | Java | JVM | Client Binding |
Doozer | General | CP | Go | Client Binding | |
Etcd | General | Mixed (1) | Go | Client Binding/HTTP | |
SmartStack | Dedicated | AP | Ruby | haproxy/Zookeeper | Sidekick (nerve/synapse) |
Eureka | Dedicated | AP | Java | JVM | Java Client |
NSQ (lookupd) | Dedicated | AP | Go | Client Binding | |
Serf | Dedicated | AP | Go | Local CLI | |
Spotify (DNS) | Dedicated | AP | N/A | Bind | DNS Library |
SkyDNS | Dedicated | Mixed (2) | Go | HTTP/DNS Library |
(1) If using the consistent parameter, inconsistent reads are possible
(2) If using a caching DNS client in front of SkyDNS, reads could be inconsistent
上面表格中,前三个是通用的,后面都是各大公司自己造的轮子,应用范围并不广,我也就不深入研究了。
此外,这篇文章是14年写的,当时它并没有研究Consul,放到表格中,Consul则应该是General、CP、Go、No dependency、Http/DNS Library。
截止到今天,除了容器编排框架k8s、istio/envoy自己实现了服务发现机制(他们也兼容第三方的服务发现工具),似乎也没有其他的知名的服务发现框架出现了。
下面我就zookeeper、etcd、consul这三款进行下比较。
比较
ZooKeeper
官网这么介绍ZooKeeper的,翻译过来,ZooKeeper的功能有:
1. 作为配置信息的存储的中心服务器
2. 命名服务
3. 分布式同步
4. 分组服务
能看出,ZooKeeper并不只是作为服务发现框架使用的,它非常庞大。
如果只是打算将ZooKeeper作为服务发现工具,就需要用到其配置存储和分布式同步的功能。前者可以理解成具有一致性的KV存储,后者提供了ZooKeeper特有的watcher注册于异步通知机制,ZooKeeper能将节点的状态实时异步通知给ZooKeeper客户端。
ZooKeeper使用
ZooKeeper的使用流程如下:
1. 确保有所选语言的sdk,理论上github上第三方的库有一些,仔细筛选一下应该可以用。
2. 调用zookeeper接口连接zookeeper服务器。
3. 注册自身服务
4. 通过watcher获取监听服务的状态
5. 服务提供者需自行保持与zookeeper服务器的心跳。
《Zookeeper C API 指南》(http://www.cnblogs.com/haippy/archive/2013/02/21/2920280.html)写了八篇文章介绍了如何使用ZooKeeper的C语言API。
总得来说,ZooKeeper需要胖客户端,每个客户端都需要通过其SDK与ZooKeeper服务保活,增加了编写程序的复杂性。此外,还提供api实现服务注册与发现逻辑,需要服务的消费者实现服务提供者存活的检测。
etcd
etcd是一个采用http协议的分布式键值对存储系统,因其易用,简单。很多系统都采用或支持etcd作为服务发现的一部分,比如kubernetes。但正事因为其只是一个存储系统,如果想要提供完整的服务发现功能,必须搭配一些第三方的工具。
比如配合etcd、Registrator、confd组合,就能搭建一个非常简单而强大的服务发现框架。但这种搭建操作就稍微麻烦了点,尤其是相对consul来说。所以etcd大部分场景都是被用来做kv存储,比如kubernetes。
consul
相较于etcd、zookeeper,consul最大的特点就是:它整合了用户服务发现普遍的需求,开箱即用,降低了使用的门槛,并不需要任何第三方的工具。代码实现上也足够简单。
展开了说,consul的功能有:
1. 通过DNS或HTTP,应用能轻易地找到它们依赖的系统
2. 提供了多种健康检查方式:http返回码200,内存是否超限,tcp连接是否成功
3. KV存储,并提供http api
4. 多数据中心,这点是zookeeper所不具备的。
consul使用
相比于zookeeper的服务发现使用,consul并不需要专门的sdk集成到服务中,因此它不限制任何语言的使用。我们看看consul一般是怎么使用的。
1. 每台服务器上都要安装一个consul agent。
2. consul agent支持通过配置文件注册服务,或者在服务中通过http接口来注册服务。
3. 注册服务后,consul agent通过指定的健康检查方式,定期检查服务是否存活。
4. 如果服务想查询其他服务的存活状态,只需要与本机的consul agent发起一次http请求或者dns请求即可。
简单点说,consul的使用不依赖任何sdk,依靠简单的http请求就能满足服务发现的所有逻辑。
不过,服务每次都从consul agent获取其他服务的存活状态,相比于zookeeper的watcher机制,实时性稍差一点,需考虑如何尽可能提高实时性,问题不会很大。
总结
zookeeper | 1.功能强大,不仅仅只是服务发现 2.提供watcher机制能实时获取服务提供者的状态 3.dubbo等框架支持 | 1.没有健康检查 2.需在服务中集成sdk,复杂度高 3.不支持多数据中心 | sdk | Paxos |
consul | 1.简单易用,不需要集成sdk 2.自带健康检查 3.支持多数据中心 4.提供web管理界面 | 1.不能实时获取服务信息的变化通知 | http/dns | Raft |
etcd | 1.简单易用,不需要集成sdk 2.可配置性强 | 1.没有健康检查 2.需配合第三方工具一起完成服务发现 3.不支持多数据中心 | http | Raft |
为了以后支持多数据中心,同时为了快速支持不同的语言比如nodejs、python服务,我会选择consul作为我们的服务发现框架,但是实时获取服务信息变化通知的问题需尽可能减小。
参考文献:
Consul vs. Other Software(https://www.consul.io/intro/vs/index.html)
服务发现:Zookeeper vs etcd vs Consul(http://dockone.io/article/667)
Consul vs 其他软件(https://skyao.gitbooks.io/learning-consul/content/introduction/consul_vs_other_software.html)
Comparing ZooKeeper and Consul(https://www.slideshare.net/IvanGlushkov/zookeeper-vs-consul-41882991)