Apche Dubbo
- RPC框架,与普通的RPC框架不同的是,提供了服务治理的功能,比如服务注册、监控、路由、容错(主要基于zookeeper)
Apache Dubbo 架构图:
image.png
服务注册发现中心:(基于Zookeeper)
Zookeeper是一个高性能的分布式协调中间件,所谓分布式协调中间件的作用就是通过并发工具包来协调线程的访问控制,比如访问顺序控制。zookeeper并不是注册中心,只是基于Zookeeper本身的特性可以实现注册中心这个场景而已
Zookeeper的数据结构
zookeeper的数据结构和分布式文件系统类似,是一种层次化得属性结构。和文件系统不同的是,Zookeeper的数据是结构化存储的,并没有在物理上出现文件或目录。
zookeeper树中的每一个节点成为znode。Znode维护了一个stat状态信息。其中包括数据变化的时间和版本等。并且每一个znode节点可以设置一个value值,Zookeeper并不用于通用的数据库或者大容量的对象存储,他只是协调和管理相关的数据。所以value的大小不建议设置的非常大,较大的数据会带来更大的网络开销。
Zookeeper每个节点的数据都是允许读写的,读代表获取指定znode节点上的value值,写标识修改指定znode上的value值。
节点的创建规则和文件系统中文件创建规则类似,必须按照层级创建。如需创建/node/node1/node1-1,则必须先创建/node/node1这两个层级节点
图片来源:
Zookeeper特性
Zookeeper中的znode被创建的时候,需要指定节点的类型,节点类型:
- 持久化节点,节点数据会被持久化到磁盘
- 临时节点,节点的生命周期和创建该节点的客户端生命周期保持一致,一旦客户端会话结束,则该客户端创建的临时节点也会被自动删除
- 有序节点:在创建节点后边会增加一个递增的序列,该序列在同级父节点下是唯一的。并且持久化节点和临时节点都可设置为有序节点,也就是持久化有序节点和临时有序节点
在3.5.3版本后,又新增了两种节点类型 - 容器节点,当容器节点下最后一个子节点被删除时,容器节点就会自动被删除
- TTL节点,针对持久化节点或者持久化有序节点。我们可以设置一个存活时间,如果在存活时间内,该节点没有任何修改并且没有任何子节点,他就会自动被删除。
同级目录下,节点名称必须是唯一的!!!!!!!
Watcher机制
Zookeeper提供了一种对znode节点 订阅/通知机制。当znode节点状态发生变化时,或者zookeeper客户端链接状态发生变化时,会触发事件通知。这个机制在服务注册与发现中,对服务调用者及时感知服务提供者变化提供非常好的解决方案
zookeeper 在 Java API中 提供了 3种机制对znode进行注册监听。
- getData(),用于获取指定节点的value信息,并且可以注册监听,当监听节点进行创建修改删除的操作时,会触发相应的事件通知。
- getChildren(), 用户获取指定节点下的所有子节点,并且允许注册监听,当监听节点进行创建修改删除的操作时,会触发相应的事件通知。
- exists(),用于判断节点是否存在,同样可以注册针对指定节点的监听,当监听节点进行创建修改删除的操作时,会触发相应的事件通知。
Watcher的事件的触发都是一次性的,比如客户端通过getData("/node",true)注册监听,如果/node节点发生数据修改,那么该客户端会受到一个修改事件通知,但是/node再次发生变化时,客户端就无法再收到Watcher事件。所以客户端必须要在收到事件回调中再次注册监听事件
常见的应用场景
1、分布式锁
使用zookeeper的临时节点的特性以及同级节点的唯一性排他锁()
- 获取锁的过程
在获取排他锁时,所有的客户端都去zookeeper服务器上 /Exclusive_Locks节点下创建一个临时节点/lock/.Zookeepr基于同级节点的唯一性,会保证所有的客户端只有一个客户端可以创建成功,创建成功的客户端就获取到了排它锁,没有获取到排它锁的客户端就需要Watcher机制监听/Exclusive_Locks下的节点变更事件,用于实时监听/lock节点的变化情况以作出相应 - 释放锁的过程
在获取锁的过程中,我们定义释节点/lock为临时节点。那么在下面两种情况下,就会自动释放锁:
1)获取锁的客户因为异常断开了与服务端的链接,基于临时节点的特性,/lock节点会被自动删除
2)获取锁的客户端执行完业务逻辑后,主动删除创建的/lock临时节点
当/lock节点被删除后,会触发Watcher监听事件,通知所有监听了 /Exclusive_Locks 子节点变化的客户端。这些客户端收到通知后,再次发起创建/lock节点的操作来获取排它锁
2.Master选举
Master选举是分布式中保证服务高可用的常见场景。项目通常采用集群模式,当一个机器宕机后,集群中其他节点会接替故障节点继续工作。这种场景下,就在集群中先选取一个master节点,剩余节点作为本分节点随时待命。当master故障后,在备份节点中选取一个master节点继续提供服务。
Zookeeper可以帮助集群中的节点实现Master选举。
Zookeeper有两种方式可以实现Master选举场景 - 同一级节点不能重复创建一个已经存在的节点。类似于分布式锁的实现,三台机器同时去创建一个临时节点,其他两个对改节点进行监听,如果Master节点不存活了,其他客户端就会重新注册节点,发起Master选举操作
- 利用临时节点的有序性
后一个节点监听前一个节点的删除事件,如果前一个节点删除了,就触发重新选举。把当前节点置为Master主节点
Zookeeper 注册中心的实现原理
image.png
当Dubbo服务启动的时候,会去Zookeeper服务器上的/dubbo/com.bob.dubbo.service.CityDubboService/providers目录下创建当前服务的URL,其中
- com.bob.dubbo.service.CityDubboService是发布服务的接口全路径名称
- providers:服务提供者类型
-
dubbo://ip:port 表示该服务发布的协议类型及访问地址。其中URL为临时节点,其他皆为持久化节点
这里使用临时节点的好处是,如果注册节点服务器下线了,那么这个服务器的URL地址就会在Zookeeper地址上被移除 - consumer: 当服务消费者启动时,会对com.bob.dubbo.service.CityDubboService/providers节点下的子节点注册Watcher监听,这样就可以感知服务提供方的上下线变化,防止请求发送到已下线的服务器造成访问失败。同时消费者会在consumer下写下自己的URL,这样做的目的是可以在监控平台上就看到某个dubbo服务正在被那些应用调用。最重要的是,dubbo服务的消费者如果需要调用CityDubboService服务,那么它会先去/dubbo/com.bob.dubbo.service.CityDubboService/providers路径下获取所有的该服务提供方的URL列表,然后通过负载均衡算法计算出一个地址进行远程访问。
作者:一个头发茂密的程序员