前言
什么是服务注册?
一个服务将其位置信息在“中心注册节点”注册的过程。该服务一般会将它的主机IP地址以及端口号进行注册,有时也会有服务访问的认证信息,使用协议,版本号,以及关于环境的一些细节信息。
什么是服务发现
服务发现就是服务提供者将自己提供的地址post或者update到服务中介,服务消费者从服务中介那里get自己想要的服务的地址。
但是有两个问题:
- 第一个问题:如果有一个服务提供者宕机,那么中介的key/value中会有一个不能访问的地址,该怎么办?
- 回答:心跳机制。服务提供者需要每隔5s左右向服务中介汇报存活,服务中介将服务地址和汇报时间记录在zset数据结构的value和score中。服务中介需要每隔10s左右检测zset数据结果,踢掉汇报时间严重落后的地址。这样就可以保证服务列表中地址的有效性
- 第二个问题:服务地址变动时如何通知消费者。有两种解决方案。
- 第一种是轮询,消费者每隔几秒查询服务列表是否有改变。如果服务地址很多,查询会很慢。这时候可以引入服务版本号机制,给每个服务提供一个版本号,在服务变动时,递增这个版本号。消费者只需要轮循这个版本号的变动就可知道服务列表是否发生了变化
- 第二种是pubsub。这种方式及时性要明显好于轮循。为了减少对线程和连接的浪费,我们使用单个pubsub广播全局版本号的变动。所谓全局版本号就是任意服务列表发生了变动,这个版本号都会递增。接收到版本变动的消费者再去检查各自的依赖服务列表的版本号是否发生了变动。这种全局版本号也可以用于第一种轮询方案。
CAP理论
CAP理论是分布式架构中重要理论
- 一致性(Consistency) (所有节点在同一时间具有相同的数据)
- 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
- 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)
关于P的理解,我觉得是在整个系统中某个部分,挂掉了,或者宕机了,并不影响整个系统的运作或者说使用,而可用性是,某个系统的某个节点挂了,但是并不影响系统的接受或者发出请求,CAP 不可能都取,只能取其中2个。原因是
(1)如果C是第一需求的话,那么会影响A的性能,因为要数据同步,不然请求结果会有差异,但是数据同步会消耗时间,期间可用性就会降低。
(2)如果A是第一需求,那么只要有一个服务在,就能正常接受请求,但是对与返回结果变不能保证,原因是,在分布式部署的时候,数据一致的过程不可能想切线路那么快。
(3)再如果,同事满足一致性和可用性,那么分区容错就很难保证了,也就是单点,也是分布式的基本核心,好了,明白这些理论,就可以在相应的场景选取服务注册与发现了。
Consul、zookeeper、etcd、eureka对比结论
选型 | 开发语言 | 接口(多语言能力) | 一致性算法|CAP定理 | 服务健康检查 | 多数据中心 | kv存储服务 | watch支持 | |
---|---|---|---|---|---|---|---|---|
zookeeper | java | sdk客户端 | Paxos | CP | (弱)长连接,keepalive | 支持 | 支持 | |
consul | go | http/dns | Raft | CA | 服务状态,内存,硬盘等 | 支持 | 全量/支持long polling | |
Etcd | go | http/grpc | Raft | CP | 连接心跳 | 支持 | 支持 long polling | |
Doozer | go |
由于eureka在2018年已经宣布放弃维护,这里就不再推荐使用了。
开发语言:
- 采用java开发,安装的时候需要部署java环境
- 采用golang开发,所有依赖都编译到了可执行程序中,即插即用。
zookeeper
Zookeeper 是一个开源的分布式协调服务,目前由 Apache 进行维护。Zookeeper 可以用于实现分布式系统中常见的发布/订阅、负载均衡、命令服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。它具有以下特性:
- 顺序一致性:从一个客户端发起的事务请求,最终都会严格按照其发起顺序被应用到 Zookeeper 中;
- 原子性:所有事务请求的处理结果在整个集群中所有机器上都是一致的;不存在部分机器应用了该事务,而另一部分没有应用的情况;
- 单一视图:所有客户端看到的服务端数据模型都是一致的;
- 可靠性:一旦服务端成功应用了一个事务,则其引起的改变会一直保留,直到被另外一个事务所更改;
- 实时性:一旦一个事务被成功应用后,Zookeeper 可以保证客户端立即可以读取到这个事务变更后的最新状态的数据。
zookeeper的功能
- 作为配置信息的存储的中心服务器
- 命名服务
- 分布式同步
- 分组服务
能看出,zookeeper并不只是作为服务发现框架使用的,它非常庞大。
如果只是打算将zookeeper作为服务发现工具,就需要用到其配置存储和分布式同步的功能。前者可以理解成具有一致性的kv存储,后者提供了zookeeper特有的watcher注册于异步通知机制,zookeeper能将节点的状态实时异步通知给zookeeper客户端。
zookeeper的使用流程
- 确保有所选语言的sdk,理论上github上第三方的库有一些,仔细筛选一下应该可以用。
- 调用zookeeper接口连接zookeeper服务器。
- 注册自身服务
- 通过watcher获取监听服务的状态
- 服务提供者需自行保持与zookeeper服务器的心跳。
优点
- 功能强大,不仅仅只是服务发现
- 提供watcher机制能实时获取服务提供者的状态
- dubbo等框架支持
为什么不使用zookeeper呢?
- zookeeper的部署和维护比较复杂,管理员需要掌握一系列的知识和技能。而zookeeper所使用的Paxos强一致性算法也素来是以复杂难懂而闻名于世;并且,zookeeper的使用也比较复杂。
- java编写,由于java偏向于重型应用,会引入大量的依赖。而运维人员则希望保持强一致、高可用的机器集群尽可能简单,维护起来也不容易出错。
- 发展缓慢,Apache基金会庞大的结构以及松散的管理导致项目发展缓慢。
etcd
etcd是一个采用http协议的分布式键值对存储系统,因其易用,简单。很多系统都采用或支持etcd作为服务发现的一部分,比如kubernetes。但正事因为其只是一个存储系统,如果想要提供完整的服务发现功能,必须搭配一些第三方的工具。
比如配合etcd、Registrator、confd组合,就能搭建一个非常简单而强大的服务发现框架。但这种搭建操作就稍微麻烦了点,尤其是相对consul来说。所以etcd大部分场景都是被用来做kv存储,比如kubernetes。
consul
概述
Consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。服务部署简单,只有一个可运行的二进制的包。每个节点都需要运行agent,他有两种运行模式server和client。每个数据中心官方建议需要3或5个server节点以保证数据安全,同时保证server-leader的选举能够正确的进行。
Consul包含多个组件,但是作为一个整体,为你的基础设施提供服务发现和服务配置的工具。他提供以下关键特性:
- 内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等)。
- 服务发现(Service Discovery):
- Consul提供了通过DNS或者HTTP接口的方式来注册服务和发现服务。一些外部的服务通过Consul很容易的找到它所依赖的服务。
- 服务发现的实现是通过服务提供方注册到consul上(http或dns方式),然后,服务使用方就可以通过consul获取到所需的服务了,注册及服务获取是通过consul提供的API来完成(http)
- 成员管理和消息广播 采用GOSSIP协议,支持ACL访问控制。
- ACL技术在路由器中被广泛采用,它是一种基于包过滤的流控制技术。控制列表通过把源地址、目的地址及端口号作为数据包检查的基本元素,并可以规定符合条件的数据包是否允许通过。
- gossip就是p2p协议。他主要要做的事情是,去中心化。 这个协议就是模拟人类中传播谣言的行为而来。首先要传播谣言就要有种子节点。种子节点每秒都会随机向其他节点发送自己所拥有的节点列表,以及需要传播的消息。任何新加入的节点,就在这种传播方式下很快地被全网所知道。
- 健康检查(Health Checking):
- Consul的Client可以提供任意数量的健康检查,既可以与给定的服务相关联(“webserver是否返回200 OK”),也可以与本地节点相关联(“内存利用率是否低于90%”)。操作员可以使用这些信息来监视集群的健康状况,服务发现组件可以使用这些信息将流量从不健康的主机路由出去。
- consul自带健康检查机制以及一个web UI界面(consul_IP:8500/ui)
- Key/Value存储:
- 应用程序可以根据自己的需要使用Consul提供的Key/Value存储。
- Consul提供了简单易用的HTTP接口,结合其他工具可以实现动态配置、功能标记、领袖选举等等功能。
- 安全服务通信:
- Consul可以为服务生成和分发TLS证书,以建立相互的TLS连接。
- 意图可用于定义允许哪些服务通信。服务分割可以很容易地进行管理,其目的是可以实时更改的,而不是使用复杂的网络拓扑和静态防火墙规则。
- 多数据中心:
- Consul支持开箱即用的多数据中心. 这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。
Consul 使用起来也较为简单,使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。
client
- CLIENT表示consul的client模式,就是客户端模式。是consul节点的一种模式,这种模式下,所有注册到当前节点的服务会被转发到SERVER,本身是不持久化这些信息
server
- SERVER表示consul的server模式,表明这个consul是个server,这种模式下,功能和CLIENT都一样,唯一不同的是,它会把所有的信息持久化的本地,这样遇到故障,信息是可以被保留的。
server-leader
- 中间那个SERVER下面有LEADER的字眼,表明这个SERVER是它们的老大,它和其它SERVER不一样的一点是,它需要负责同步注册的信息给其它的SERVER,同时也要负责各个节点的健康监测。
agent
- 组成 consul 集群的每个成员上都要运行一个 agent,可以通过 consul agent 命令来启动。agent 可以运行在 server 状态或者 client 状态。自然的,运行在 server 状态的节点被称为 server 节点;运行在 client 状态的节点被称为 client 节点。
consul的功能
- 通过DNS或HTTP,应用能轻易地找到它们依赖的系统
- 提供了多种健康检查方式:http返回码200,内存是否超限,tcp连接是否成功
- kv存储,并提供http api
- 多数据中心,这点是zookeeper所不具备的。
相比于zookeeper的服务发现使用,consul并不需要专门的sdk集成到服务中,因此它不限制任何语言的使用。
consul使用流程
- 每台服务器上都要安装一个consul agent。
- consul agent支持通过配置文件注册服务,或者在服务中通过http接口来注册服务。
- 注册服务后,consul agent通过指定的健康检查方式,定期检查服务是否存活。
- 如果服务想查询其他服务的存活状态,只需要与本机的consul agent发起一次http请求或者dns请求即可。
简单点说,consul的使用不依赖任何sdk,依靠简单的http请求就能满足服务发现的所有逻辑。
不过,服务每次都从consul agent获取其他服务的存活状态,相比于zookeeper的watcher机制,实时性稍差一点,需考虑如何尽可能提高实时性,问题不会很大。
服务管理
服务注册
consul支持两种方式实现服务注册,一种是通过consul的服务注册http API,由服务自己调用API实现注册,另一种方式是通过json配置文件实现注册,将需要注册的服务以json格式的配置文件给出。consul官方建议使用第二种方式。
服务发现
consul支持两种方式实现服务发现,一种是通过http API来查询有哪些服务,另外一种是通过consul agent 自带的DNS(8600端口),域名是以NAME.service.consul的形式给出,NAME即在定义的服务配置文件中,服务的名称。DNS方式可以通过check的方式检查服务。
服务间的通信协议
consul使用gossip协议管理成员关系、广播消息到整个集群,他有两个gossip pool(LAN pool和WAN pool),LAN pool是同一个数据中心内部通信的,WAN pool是多个数据中心通信的,LAN pool有多个,WAN pool只有一个
使用场景
Consul的应用场景包括服务发现、服务隔离、服务配置:
- 服务发现场景中,consul作为注册中心,服务地址被注册到consul中以后,可以使用consul提供的dns、http接口查询,consul支持health check。
- 服务隔离场景中,consul支持以服务为单位设置访问策略,能同时支持经典的平台和新兴的平台,支持tls证书分发,service-to-service加密。
- 服务配置场景中,consul提供key-value数据存储功能,并且能将变动迅速地通知出去,通过工具consul-template可以更方便地实时渲染配置文件。
每个被注册到consul中的node上,都部署一个consul agent,这个agent负责对本地的服务进行监控检查,以及将查询请求转发给consul server。 consul server负责存放、备份数据(使用raft协议保证一致性),通常要有多台形成集群,选举出一个leader。 查询服务地址的时候,可以直接向consul server发起查询,也可以通过consul agent查询,后者将转发给consul server。 如果是多数据中心,每个数据中心部署一组consul server。跨数据中心查询通过本数据中心的consul server进行。 注意:多数据中心的时候,不同数据中心的consul server之间不会同步key-value数据。
zookeeper和consul比较
-
开发语言方面,zookeeper采用java开发,安装的时候需要部署java环境;consul采用golang开发,所有依赖都编译到了可执行程序中,即插即用。
-
部署方面,zookeeper一般部署奇数个节点方便做简单多数的选举机制。consul部署的时候分server节点和client节点(通过不同的启动参数区分),server节点做leader选举和数据一致性维护,client节点部署在服务机器上,作为服务程序访问consul的接口。
-
zookeeper不支持多数据中心,consul可以跨机房支持多数据中心部署,有效避免了单数据中心故障不能访问的情况。
-
链接方式上,zookeeper client api和服务器保持长连接,需要服务程序自行管理和维护链接有效性,服务程序注册回调函数处理zookeeper事件,并自己维护在zookeeper上建立的目录结构有效性(如临时节点维护);consul 采用DNS或者http获取服务信息,没有主动通知,需要自己轮训获取
-
工具方面,zookeeper自带一个cli_mt工具,可以通过命令行登录zookeeper服务器,手动管理目录结构。consul自带一个Web UI管理系统, 可以通过参数启动并在浏览器中直接查看信息。
-
https://www.jianshu.com/p/9bcbb7c26539
-
https://www.cnblogs.com/traditional/p/9445930.html