你听说过ap、cap、cp 这些概念吗?还有leader、rpc、registry、sla、server、watch、

你听说过AP、CAP、CP这些概念吗?还有Leader、RPC、Registry、SLA、Server、Watch、ZAB、ZK、Zookeeper这些名词,你都懂它们是什么意思吗?今天咱们就来聊聊怎么把Zookeeper用在注册中心上,同时避开那些容易掉进去的陷阱。 Zookeeper就像一个大管家,负责管理服务提供者和消费者的地址信息。你想,服务提供者启动的时候,不就是把自己的IP、端口号、版本号这些信息全都扔到Zookeeper里吗?这就好比是给自己打了个电话报个到,告诉大家我在线呢。而且为了让大家知道我一直都在,服务提供者还会定期跟Zookeeper说一声“我还活着”。 那消费者呢?消费者第一次用服务的时候,就去Zookeeper那里问个好,把所有服务提供者的地址都拉到自己的本地内存里存着。以后每次调用服务,直接查本地内存就能找到对应的服务器。这就相当于你提前定了一份报纸,以后想看新闻直接翻报纸就行。要是地址有变动了,Zookeeper就会马上把这个消息推送给所有订阅者,消费者刷新一下缓存就可以继续调用服务了。 其实说白了,Zookeeper注册中心就是解决了两个大问题:谁在线?怎么连上它?它把这些问题都给解决了。那Zookeeper具体是怎么做到这一点的呢?其实它是把所有的服务注册信息做成了一棵树。每个节点代表一个服务,路径就是它的地址。 比如说你想注册一个服务,就在ZK的/service/{version}/{ip:port}路径下创建一个临时有序节点。消费者第一次调用的时候,会把这个路径下的所有信息全量拉回本地;以后每次调用就通过Watch机制来“看增量”,也就是只关心最新的变化。这样就能保证数据及时又不过度耦合。 如果某个节点消失了(比如机器宕机),ZK就会自动把消费者缓存里的对应条目给删掉;如果有新机器上线了,同样路径下又出现了节点,消费者就会再次收到更新通知。 除此之外还有个心跳检测机制:客户端和服务器之间保持一个长连接,每秒发个包检测一下对方还活着没有。如果超时阈值(默认30秒)到了还没收到回应,就会认为节点挂了,把它给临时删除掉。 至于Watch机制嘛,就是一种推拉结合的魔法:消费者对指定的路径设置一个Watcher(监视器),服务器端的数据一变动就把事件推送给客户端;客户端收到事件后再主动去拉取增量数据。这样既保证了及时性又不会让系统过于复杂。 不过呢,用Zookeeper做注册中心也有它的难处。根据CAP理论来说,一致性(C)、可用性(A)、分区容忍性(P)这三个原则你不可能同时满足所有的。Zookeeper为了追求强一致性(C),往往就得牺牲可用性(A)。 领导者选举是个大问题。如果领导者挂了或者网络分区了,就得重新选举新的领导者出来接管工作。这个过程有时候长达30-120秒呢!这意味着在这段时间里整个集群对外是不可用的状态。 但在微服务架构里这可不行啊!网络闪断是常有的事;如果ZK在这种情况下失去了Leader,就得重新选举很长时间;这会直接拖垮整个微服务架构的弹性和响应速度。 所以呢?在注册中心这种场景下其实更像是AP模型而不是CP模型——先保证有人能回应(A),再谈数据是否一致(C)。 可惜的是ZAB协议为了强一致性把“最终一致性”给锁死了;这就天然地和注册中心的SLA(服务等级协议)背道而驰了。 总的来说用Zookeeper做注册中心有好处也有坏处。好处就是心跳机制和Watch机制配合得很好;坏处就是Leader选举耗时太长;特别是在云环境里高频网络抖动容易让服务雪藏起来。 所以在选择的时候要权衡利弊:如果你的业务能忍受“偶尔不一致”或者是服务生命周期很短重启也很快;那Zookeeper还是性价比很高的选择;如果你的业务追求毫秒级可用或者是高并发调用;建议还是另选别的AP型方案比较好。 最后给大家推荐几本书吧:《分布式系统原理与算法》、《Zookeeper实战》、《服务网格技术全景》——把理论、实战和趋势都了解一遍再回头看ZK,视角就完全不一样了。