1. consul的基本介绍
在分布式架构中,服务治理是一个重要的问题。在没有服务治理的分布式集群中,各个服务之间通过手工或者配置的方式进行服务关系管理,遇到服务关系变化或者增加服务的时候,人肉配置极其麻烦且容易出错。之前在一个C/C++项目中,采用ZooKeeper进行服务治理,可以很好的维护服务之间的关系,但是使用起来较为麻烦。现在越来越多新的项目采用consul进行服务治理,各方面的评价都优于ZooKeeper,经过几天的研究,这里做一个总结。
zookeeper和consul比较
开发语言方面,zookeeper采用java开发,安装的时候需要部署java环境;consul采用golang开发,所有依赖都编译到了可执行程序中,即插即用。
部署方面,zookeeper一般部署奇数个节点方便做简单多数的选举机制。consul部署的时候分server节点和client节点(通过不同的启动参数区分),server节点做leader选举和数据一致性维护,client节点部署在服务机器上,作为服务程序访问consul的接口。
一致性协议方面,zookeeper使用自定义的zab协议,consul的一致性协议采用更流行的Raft。
zookeeper不支持多数据中心,consul可以跨机房支持多数据中心部署,有效避免了单数据中心故障不能访问的情况。
链接方式上,zookeeper client api和服务器保持长连接,需要服务程序自行管理和维护链接有效性,服务程序注册回调函数处理zookeeper事件,并自己维护在zookeeper上建立的目录结构有效性(如临时节点维护);consul 采用DNS或者http获取服务信息,没有主动通知,需要自己轮训获取。
工具方面,zookeeper自带一个cli_mt工具,可以通过命令行登录zookeeper服务器,手动管理目录结构。consul自带一个Web UI管理系统, 可以通过参数启动并在浏览器中直接查看信息。
Consul是一个用来实现分布式系统的服务发现与配置的开源工具。他主要由多个组成部分:
服务发现:客户端通过Consul提供服务,类似于API,MySQL,或者其他客户端可以使用Consul发现服务的提供者。使用类似DNS或者HTTP,应用程序和可以很轻松的发现他们依赖的服务。
检查健康:Consul客户端可以提供与给定服务相关的健康检查(Web服务器返回200 ok)或者本地节点(“内存利用率低于90%”)。这些信息可以监控集群的运行情况,并且使访问远离不健康的主机组件。
键值对存储:应用程序可以使用Cousul的层级键值对。
多数据中心:Consul有开箱及用的多数据中心。
client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群.
server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网与其他数据中心通讯. 每个数据中心的 server 数量推荐为 3 个或是 5 个.
agent
组成 consul 集群的每个成员上都要运行一个 agent,可以通过 consul agent
命令来启动。agent 可以运行在 server 状态或者 client 状态。自然的,运行在 server 状态的节点被称为 server 节点;运行在 client 状态的节点被称为 client 节点。
client 节点
负责转发所有的 RPC 到 server 节点。本身无状态,且轻量级,因此,可以部署大量的 client 节点。
server 节点
负责组成 cluster 的复杂工作(选举、状态维护、转发请求到 lead),以及 consul 提供的服务(响应 RCP 请求)。考虑到容错和收敛,一般部署 3 ~ 5 个比较合适。
Consul内幕
术语
代理(agent):代理是Consul集群上每个成员的守护进程,它是由consul agent开始运行。代理能够以客户端或服务器模式运行。由于所有节点都必须运行代理,所以将节点引用为客户端或服务器更为简单,但还有其他实例的代理。所有代理可以运行DNS或HTTP接口,并负责运行检查和保持服务同步。
客户端:客户端可以将所有RPC请求转发到服务器的代理。客户端是相对无状态的。客户端执行的唯一后台活动是LANgossip池。它消耗最小的资源开销和少量的网络带宽。
服务器端:服务器端是具有扩展的功能的代理,它主要参与维护集群状态,响应RPC查询,与其他数据中心交换WAN gossip ,以及向上级或远程数据中心转发查询。
数据中心:虽然数据中心的定义似乎很明显,但仍有一些细微的细节必须考虑。我们将一个数据中心定义为一个私有、低延迟和高带宽的网络环境。这不包括通过公共互联网的通信,但是为了我们的目的,单个EC2区域内的多个可用区域将被视为单个数据中心的一部分
Gossip:consul是建立在serf之上的,它提供了一个完整的gossip协议,用在很多地方。Serf提供了成员,故障检测和事件广播。Gossip的节点到节点之间的通信使用了UDP协议。
LAN Gossip:指在同一局域网或数据中心的节点上的LAN Gossip池。
WAN Gossip:指包含服务器的WAN Gossip池,这些服务器在不同的数据中心,通过网络进行通信。
一致性协议采用 Raft 算法,用来保证服务的高可用.
成员管理和消息广播 采用GOSSIP协议,支持ACL访问控制。
ACL技术在路由器中被广泛采用,它是一种基于包过滤的流控制技术。控制列表通过把源地址、目的地址及端口号作为数据包检查的基本元素,并可以规定符合条件的数据包是否允许通过。
gossip就是p2p协议。他主要要做的事情是,去中心化。
这个协议就是模拟人类中传播谣言的行为而来。首先要传播谣言就要有种子节点。种子节点每秒都会随机向其他节点发送自己所拥有的节点列表,以及需要传播的消息。任何新加入的节点,就在这种传播方式下很快地被全网所知道。
什么是服务注册?
一个服务将其位置信息在“中心注册节点”注册的过程。该服务一般会将它的主机IP地址以及端口号进行注册,有时也会有服务访问的认证信息,使用协议,版本号,以及关于环境的一些细节信息。
什么是服务发现?
服务发现可以让一个应用或者组件发现其运行环境以及其它应用或组件的信息。用户配置一个服务发现工具就可以将实际容器跟运行配置分离开。常见配置信息包括:ip、端口号、名称等。
当一项服务存在于多个主机节点上时,client端如何决策获取相应正确的IP和port。
在传统情况下,当出现服务存在于多个主机节点上时,都会使用静态配置的方法来实现服务信息的注册。
而当在一个复杂的系统里,需要较强的可扩展性时,服务被频繁替换时,为避免服务中断,动态的服务注册和发现就很重要。
图中,客户端的一个接口,需要调用服务A-N。客户端必须要知道所有服务的网络位置的,以往的做法是配置是配置文件中,或者有些配置在数据库中。这里就带出几个问题:
需要配置N个服务的网络位置,加大配置的复杂性
服务的网络位置变化,都需要改变每个调用者的配置
集群的情况下,难以做负载(反向代理的方式除外)
总结起来一句话:服务多了,配置很麻烦,问题多多
既然有这些问题,那么服务发现就是解决这些问题的。话说,怎么解决呢?我们再看一张图
与之前一张不同的是,加了个服务发现模块。图比较简单,这边文字描述下。服务A-N把当前自己的网络位置注册到服务发现模块(这里注册的意思就是告诉),服务发现就以K-V的方式记录下,K一般是服务名,V就是IP:PORT。服务发现模块定时的轮询查看这些服务能不能访问的了(这就是健康检查)。客户端在调用服务A-N的时候,就跑去服务发现模块问下它们的网络位置,然后再调用它们的服务。这样的方式是不是就可以解决上面的问题了呢?客户端完全不需要记录这些服务网络位置,客户端和服务端完全解耦!
这个过程大体是这样,当然服务发现模块没这么简单。里面包含的东西还很多。这样表述只是方便理解。
图中的服务发现模块基本上就是微服务架构中服务发现的作用了。
consul 简介
做服务发现的框架常用的有
zookeeper
eureka
etcd
consul
这里就不比较哪个好哪个差了,需要的童鞋自己谷歌百度。
那么consul是啥?consul就是提供服务发现的工具。然后下面是简单的介绍:
consul是分布式的、高可用、横向扩展的。consul提供的一些关键特性:
service discovery:consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易,一些外部服务,例如saas提供的也可以一样注册。
health checking:健康检测使consul可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面。
key/value storage:一个用来存储动态配置的系统。提供简单的HTTP接口,可以在任何地方操作。
multi-datacenter:无需复杂的配置,即可支持任意数量的区域。
我们这里会介绍服务发现,健康检查,还有一些基本KV存储。多数据中心有机会另一篇文章再说。
总结:只要知道它是解决我上一部分提出的问题就行,其它的东西慢慢理解
consul的几个概念
上图是我从consul官方文档抠出来的。
我们只看数据中心1,可以看出consul的集群是由N个SERVER,加上M个CLIENT组成的。而不管是SERVER还是CLIENT,都是consul的一个节点,所有的服务都可以注册到这些节点上,正是通过这些节点实现服务注册信息的共享。除了这两个,还有一些小细节,一一简单介绍。
CLIENT
CLIENT表示consul的client模式,就是客户端模式。是consul节点的一种模式,这种模式下,所有注册到当前节点的服务会被转发到SERVER,本身是不持久化这些信息。
SERVER
SERVER表示consul的server模式,表明这个consul是个server,这种模式下,功能和CLIENT都一样,唯一不同的是,它会把所有的信息持久化的本地,这样遇到故障,信息是可以被保留的。
SERVER-LEADER
中间那个SERVER下面有LEADER的字眼,表明这个SERVER是它们的老大,它和其它SERVER不一样的一点是,它需要负责同步注册的信息给其它的SERVER,同时也要负责各个节点的健康监测。
其它信息
其它信息包括它们之间的通信方式,还有一些协议信息,算法。它们是用于保证节点之间的数据同步,实时性要求等等一系列集群问题的解决。这些有兴趣的自己看看官方文档。
相关开源项目:Zookeeper,Doozer,Etcd,强一致性的项目,这些项目主要用于服务间的协调,同时又可用于服务的注册。
什么是强一致性协议?
按照某一顺序串行执行存储对象读写操作, 更新存储对象之后, 后续访问总是读到最新值。 假如进程A先更新了存储对象,存储系统保证后续A,B,C进程的读取操作都将返回最新值。强一致性模型有几种常见实现方法, 主从同步复制, 以及quorum复制等。
http://blog.csdn.net/shlazww/article/details/38736511
2. consul的具体应用场景
1. docker、coreos 实例的注册与配置共享
2. vitess集群
3. SaaS应用的配置共享
4.与confd服务集成,动态生成nignx与haproxy配置文件
3. 优势
1. 使用 Raft 算法来保证一致性,比poxes算法更直接。zookeeper采用的时poxes算法。
Raft大概将整个过程分为三个阶段,leader election,log replication和commit(safety)。
每个server处于三个状态:leader,follower,candidate。正常情况下,所有server中只有一个是leader,其它的都是follower。server之间通过RPC消息通信。follower不会主动发起RPC消息。leader和candidate(选主的时候)会主动发起RPC消息。
首先选择一个leader全权负责管理日志复制,leader从客户端接收log entries,将它们复制给集群中的其它机器,然后负责告诉其它机器什么时候将日志应用于它们的状态机。举个例子,leader可以在无需询问其它server的情况下决定把新entries放在哪个位置,数据永远是从leader流向其它机器。一个leader可以fail或者与其他机器失去连接,这种情形下会有新的leader被选举出来。
http://www.jdon.com/artichect/raft.html
http://blog.csdn.net/cszhouwei/article/details/38374603
2. 支持多数据中心,内外网的服务采用不同的端口进行监听。这样可以避免单点故障。
zookeeper等不支持多数据中心功能的支持
3. 支持健康检查
4. 提供web界面
5. 支持http协议与dns协议接口
使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是 Paxos, 而 etcd 使用的则是 Raft.
支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等. zookeeper 和 etcd 均不提供多数据中心功能的支持.
支持健康检查. etcd 不提供此功能.
支持 http 和 dns 协议接口. zookeeper 的集成较为复杂, etcd 只支持 http 协议.
官方提供web管理界面, etcd 无此功能.
综合比较, Consul 作为服务注册和配置管理的新星, 比较值得关注和研究.
4. 架构图
图中有两个数据中心,分别为Datacenter1和Datacenter2。Consul一层支持多个数据中心,每个数据中心内,有客户端和服务器端,服务区端一般为3~5个,这样可以在稳定和性能上达到平衡,因为更多的机器会使数据同步很慢。不过客户端是没有限制的,可以有成千上万个。
数据中心到所有节点都使用的时候Gossip协议。这就意味着有一个Gossip池,其中包含给定数据中心所有的节点。客户端不需要去配置服务器地址信息,发现服务会自动完成;检测故障节点的工作不是放在服务器端,而是分布式的;数据中心被用作消息层,以便在选择leader这种重要的事情发生的时候做通知。
每个数据中心都是都是单个Raft对等设备的一部分。这意味着他们一起工作,选择一个单一的领导者——一个具有额外职责的选定的服务器。leader负责处理所有查询和事物。事物也必须作为同步协议的一部分复制到所有对等体。由于这个要求,当非领导服务器端接收到RPC请求时,就会将请求其转发给集群leader。
服务器端节点作为WANGossip池的一部分运行,WAN池和LAN池不同的是,针对网络高延迟做了优化,而且只包含其他Consul服务器的节点。这个池的目的是允许数据中心以最少的消耗方式发现对方。在线启动新的数据中心与加入现有的WAN Gossip一样简单。因为这些服务器都在这个池中运行,它还支持跨数据中心请求。当服务器收到对不同数据中心的请求时,它会将其转发到正确数据中心中的随机服务器。那个服务器可能会转发给本地的leader。
这样会使数据中心的耦合非常低,由于故障检测,连接缓存和复用,跨数据中心请求相对快速可靠。
Gossip协议(流言传播协议)
Consul使用Gossip协议来管理成员和集群广播消息,这些都是通过使用Serf库的。Serf所使用的Gossip协议基于SWIM:可伸缩的弱一致的感染模式的过程组成员协议”,并做了一些细微的修改。
Consul中的Gossip
Consul使用了两个不同的Gossip池,称为LAN池和WAN池。每个数据中心都有一个LAN池,其中包含数据中心的所有成员,包括服务器端和客户端。LAN的成员客户端可以自动发现服务器,减少所需配置的数量。分布式故障检测可以让故障检测的工具被整个集群共享,Gossip池可以快速可靠的将事件广播,比如选择leader。
WAN池是全局唯一的,所有的服务器都应该在WAN池中,而不关系数据中心在哪里。WAN池提供的成员信息允许服务器执行跨数据中心请求。集成的故障检测功能使Consul能够优雅地处理整个数据中心或者远程数据中心的一个服务器失连。
Lifeguard Enhancements
在分组软实时处理可能的情况下,SWIN假设本地节点是健康的。但在本地节点遇到CPU或者网络节点资源匮乏的时候,可能不会认为节点不健康。结果是安全检测状态可能会偶尔瘫痪,导致虚假报警。Lifeguard解决了这个问题。
Consensus 协议
Consul通过Consensus协议来提供一致性(由CAP定义)。Consensus协议是基于Raft——查找可理解的一致性算法。
Raft协议概述
Raft是一种基于Paxos的一致性算法。与Paxos相比,Raft被设计成更少的状态和更简单、更易于理解的算法。
Raft节点有三种状态:follower,candidate,leader.所有的节点初始被置于follower,在这个状态下的节点都可以收到来自leader的Log并反馈。如果在一段时间没有收到任何信息,那么他就会变成candidate状态。在candidate状态下,一个节点向其他节点发送请求,这个节点就成为了leader。Leader必须接收新Log并复制其到其他follower那里。PS:只有leader才能进行读取Log。
一旦一个集群有一个leader,他就可以接受新的Log条目。一个客户端可以请求leader附加新的Log条目。这个leader随后将Log条目写入持久存储,并复制到follower。一旦Log条目被认为已经提交,它就会被用于有限状态机。有限状态机是相对于特定应用的,对于Consul而言,我们使用MenDB来维护集群状态。
显然,我们不需要无限制的复制日志。Raft提供了一种机制,通过这种机制,让状态被记录时这个Log就会被压缩。
网络坐标
Consul使用网络断层成像系统计算集群中的节点的网络坐标。这些坐标可以计算在任何两个节点之间估计网络往返时间。这有很多有用的应用,例如找到最靠近请求节点的服务节点,或者找到在下一个失效的最接近的数据中心中的服务器。
Consul的网络坐标
在Consul里,网络坐标有几种形式:
consul rtt命令可以查询任意两个节点的网络往返之间。
显示端点和端点运行状况端点可以使用“?near =”参数根据给定节点的网络往返时间对查询的结果进行排序。
查询可以根据网络往返时间将请求从故障的数据中心服务器中转移。
坐标终点显示用于其他应用程序的原始网络坐标。
Session
Consul提供了Session机制用于构建分布式锁,Session作为节点之间的绑定,运行状况检查和键值对数据。
Session设计
Consul的session代表了具体语义一个Session中包含了节点名称,列表的健康性,行为,TTL和lock-delay。新建的Session中提供了一个可以用来识别它的ID。这个ID可与存储的键值对一起使用以获取锁定:相互排斥的咨询机制。
下图是组件之间的关系图:
Consul定制的标准在下列情况下,被定义为无效:
节点被注销
所有的健康检查都被注销
所有健康检查都在危险状态
Session被明确销毁了
TTL过期
Session无效的时候,将会被销毁,关联锁是创建的指定行为,Consul支持发布和删除。Consul支持释放和删除行为,如果没有特别指定,默认的行为为释放。
如果正在执行释放操作,与Session相关的所有的锁都会被释放掉,并且键的索引无法递增。在删除行为执行的时候,则锁和键都会被删除。这可以用于Consul自动删除条目。
这种设计常用于流言传播的故障检测器的健康监测。在默认情况下,使用基于留言传播的故障检测器作为故障检测器用来进行相关的健康检查。该故障检测器允许Consul检测持有锁的节点在发生故障时自动释放锁。这种机制让consul发生故障或者其他失败的情况下,可以继续运行下去。但是,由于,没有完美的故障检测器,有的时候,检测到的故障并不存在,也会导致锁的释放。这就意味着他并不是绝对安全的。
相反的,可以创建一个无关联的健康检测的session。这就提供了对安全性要求的虚假的不健康检测的消除提供了可能。即使现有的锁的持有者执行出现故障,你也可以自己确定是否释放Consul的锁。由于Consul的API可以强制销毁session,所以我们可以在发生故障的时候进行人为干预,防止split-brain。
第三个健康检测机制是session的TTL。当创建一个session的时候,一个TTL也被指定。如果这个TTL的间隔时间到而没有更新,则session过期,并且无法早触发。这种类型的故障检测器叫做心跳检测器。他想必基于流言传播的故障检测器的可扩展性低,因为他会对服务器造成更大的负担,但是在一些情况下很有用。TTL是session过期的时间,在到达TTL之前,consul不会让session过去,但是consul允许延迟过期。在session创建初期,session更新和leader故障转移的时候,TTL会更新。当一个TTL被使用的时候,客户端应当注意时间的偏差——时间不可能会像consul Server上那样在客户端上以相同的速率进展。我们最好设置保守的TTL值,TTL更新之前考虑时间的偏差。
最后的细微差别为session会提供锁定延迟。这个延迟会持续0-60秒。当有无效的session时,consul会防止ssession在锁定延时的时间内重新获取之前的保存的所有锁。这种延迟的目录是允许潜在的leader检测到无效后,停止并导致状态不一致的请求。虽然不是一个彻底的方式,但是可以减少很多问题。延迟默认为15秒,客户端可以将延迟设置为0来取消这个机制。
安全模型
Consul使用了流言传播协议和RPC来提供各种功能。这两个系统在设计上采用了不同的安全机制,但是,Consul的安全机制完成的共同目标为:提供机密性,完整性和认证。流言传播协议由serf提供支持,serf使用对称秘钥或者共享密码系统。RPC支持使用可选客户端认证的端到端的TLS。
这就意味着Consul有完善的安全机制可以使其在不可信的网络上运行。
威胁模型
以下是威胁模型:
非成员可以访问数据
由于恶意邮件导致集群被操控
恶意邮件造成的虚假数据
对接点拒接服务
命令行
Consul命令行
Consul使用命令行非常容易操作,我们可以通过命令consul进行命令行申请。然后接着使用agent或者member之类的子命令。只要运行不带参数的consul命令就可以查看命令列表。
$ consul usage: consul [--version] [--help] <command> [<args>]Available commands are: agent Runs a Consul agent configtest Validate config file event Fire a new event exec Executes a command on Consul nodes force-leave Forces a member of the cluster to enter the "left" state info Provides debugging information for operators join Tell Consul agent to join cluster keygen Generates a new encryption key keyring Manages gossip layer encryption keys kv Interact with the KV store leave Gracefully leaves the Consul cluster and shuts down lock Execute a command holding a lock maint Controls node or service maintenance mode members Lists the members of a Consul cluster monitor Stream logs from a Consul agent operator Provides cluster-level tools for Consul operators reload Triggers the agent to reload configuration files rtt Estimates network round trip time between nodes version Prints the Consul version watch Watch for changes in Consul
想要获得的顶的命令的帮助,可以使用-h获取帮助,如下:
$ consul join -h
Agent
Agent是Consul的核心,用来运行代理者,维护成员的信息,运行检测,处理查询信息等。
catalog
consul catalog
该命令用来接Consul目录进行交互。
列出数据中心
consul catalog datacenters
列出节点
consul catalog nodes
列出所有提供服务的节点
consul catalog nodes -service=redis
列出所有的服务器
consul catalog services
Event
consul event
event提供了一种将自定义用户事件触发到整个数据中心的机制,这些事件对Consul是不透明的,但它们可用于构建脚本基础架构,以进行自动部署,重新启动服务或执行任何其他编排操作。Event可以通过使用watch来处理。event的传播是通过流言传播协议的。
Exec
consul exec
exec命令提供了远程执行的机制。下表显示了执行此命令索要的ACL。
ACL Required | 范围 |
---|---|
agent:read | 本地agent |
session:write | 本地agent |
key:write | "_rexec"字首 |
event:write | "_rexec"字首 |
info
consul info
info命令提供了对运算符有用的各种调试信息。根据代理是客户端还是服务器,将返回不同的子系统信息。目前有几个顶级的键:
agent:提供有关agent的信息
consul:有关consul的信息——客户端或者服务器端
raft:提供有关Raft公共信息
serf_lan:提供有关LAN流言池的信息
serf_wandf:提供有关WAN流言池的信息
join
consul join
join命令让Consul代理加入一个现有集群,新的Consul代理必须与集群的至少一个现有成员共同参与现有的集群。加入该成员后,流言层接管,跨集群传播更新成员的资格状态。如果没有加入现有的集群,则代理是自己的孤立集群的一部分,其他节点可以加入。
代理可以加入其它的代理。如果已经是集群的一部分的节点加入了另一个节点,则两个节点的集群将加入成为一个集群。
Keygen
consul keygen
keygen命令生成可用于Consul代理流量加密的加密秘钥。
Keyring
consul keyring
keyring命令用于检查和修改Consul的流言池中使用的加密密钥。
Lock
lock命令提供了简单分布式锁定的机制。在KV存储中的给定前缀创建锁(或信号量),只有当被保持时,才会调用子进程。如果锁丢失或通信中断,则子进程终止。锁定器的数量可以使用-n标志进行配置。默认情况下,允许单个持有人,并且使用锁来进行互斥。这使用leader选举算法。
member
menber命令输出Consul代理人知道的当前成员名单及其状态。节点的状态只能是“alive”,“left”或“failed”。
Monitor
monitor命令用于连接和跟踪正在运行的Consul代理的日志。Monitor将显示最近的日志,然后继续遵循日志,不会退出直到中断或直到远程代理退出。
reload
reload命令触发代理程序重新加载配置文件。
Snapshot
snapshot命令具有用于保存,恢复和检查Consul服务器的状态用于容灾恢复的子命令。这些是原子的时间点快照,其中包括键值条目,服务目录,准备好的查询,会话和ACL。 Consul 0.7.1及更高版本中提供此命令。
Agent
Consul的Agent是Consul的核心。Agent维护成员的信息,注册服务,运行检测,响应查询。Agent必须作为Consul集群的一部分的每个节点上运行。任何代理可以以两种模式之一运行:客户端或者服务器。服务器节点承担了协商一致性的功能。这些节点参与了Raft,并在故障下提供了强大的一致性和可用性。服务器节点负担越来越大意味着需要在专用的实例上运行——他们比客户端节点更为资源密集。客户端节点构成了大多数的集群,并且它们很轻量,因为它们大多数操作的是服务器节点接口,维护自己状态的时间很少。
参考地址:http://www.cnblogs.com/Summer7C/p/7327109.html