目录
一、如何理解Apache Dubbo
二、ZooKeeper
zookeeper的特性
Watcher机制
常见应用场景分析
分布式锁
集群选主
统一命名服务
统一配置管理
统一集群管理
三、Apache Dubbo集成zookeeper实现服务注册
实现步骤
实现原理
四、Apache Dubbo的高级应用
集群容错
配置方式
负载均衡
配置方式
服务降级
配置方式
主机绑定规则
一、如何理解Apache Dubbo
Apache Dubbo是一个分布式框架,主要是实现多个系统的高性能,透明化调用吗,简单来说就是rpc框架,但不同的是,它提供了服务发现、注册、监控、路由、容错等
二、ZooKeeper
ZooKeeper是高性能的分布式协调中间介,需要强调的是zookeeper本身不是注册中心,只是基于他本身的特性可以实现注册中心的这个场景而已
zookeeper的数据结构
zookeeper树中的每个节点称之为Znode,每个节点的数据是允许读和写的
zookeeper的特性
zookeeper的Znode被创建的时候,需要指定节点类型,节点类型主要包含
1.持久化节点,节点数据会被持久化到磁盘
2.临时节点,节点的生命周期与创建该节点的客户端的生命周期一致,也就是说一旦该客户端的会话生命周期结束,那么该节点也会被自动删除。(基于节点的这个特性,可以实现服务注册于发现)
3.有序节点,持久化节点和临时节点都是可以是有序的节点。
3.5.3版本后,又增加了两个节点
1.ttl节点,针对持久化节点,可以设置它的过期时间
2.容器节点,当容器中的最后一个子节点被删除之后,容器也会被删除
需要注意:同一层级目录下,节点名称必须唯一
Watcher机制
Watcher 监听机制是 Zookeeper 中非常重要的特性,我们基于 zookeeper 上创建的节点,可以对这些节点绑定监听事件,比如可以监听节点数据变更、节点删除、子节点状态变更等事件,通过这个事件机制,可以基于 zookeeper实现分布式锁,发布订阅(多个订阅者同时监听某一个主题对象,当这个主题对象自身状态发生变化时,会通知所有订阅者)等功能。
Watcher 分为以下三个过程:客户端向ZK服务端注册 Watcher、服务端事件发生触发 Watcher、客户端回调 Watcher 得到触发事件情况.
触发事件种类很多,如:节点创建,节点删除,节点改变,子节点改变等。
Watcher是一次性的. 一旦被触发将会失效. 如果需要反复进行监听就需要反复进行注册.
(原理不做展开 可参考文章:Zookeeper原理之数据模型, 选举机制, 监听机制, 数据一致性处理, 分布式锁应用_啊策策的博客-CSDN博客)
注册 watcher 有 3 种方式,getData、exists、getChildren;
- 监听节点数据的变化get path [watch]
- 监听节点状态的变化 stat path [watch]
- 监听子节点增减的变化 ls path [watch]
常见应用场景分析
基于zookeeper的节点特性,可以针对很多场景提供解决方案。
分布式锁
分布式锁使用的是Zookeeper的临时有序节点
需求: 在分布式系统中, 很容出现多台主机操作同一资源的情况, 比如两台主机同时往一个文件中追加写入文本, 如果不去做任何的控制, 很有可能出现一个写入操作被另一个写入操作覆盖掉的状况.
方案: 此时我们可以来一把锁, 哪个主机获取到了这把锁, 就执行写入, 另一台主机等待; 直到写入操作执行完毕,另一台主机再去获得锁,然后写入.
这把锁就称为分布式锁, 也就是说:分布式锁是控制分布式系统之间同步访问共享资源的一种方式
实现:
使用Zookeeper的临时有序节点可以轻松实现这一需求.
所有需要执行操作的主机都去Zookeeper上创建一个临时有序节点.
然后获取到Zookeeper上创建出来的这些节点进行一个从小到大的排序.
判断自己创建的节点是不是最小的, 如果是, 自己就获取到了锁; 如果不是, 则对最小的节点注册一个监听.
如果自己获取到了锁, 就去执行相应的操作. 当执行完毕之后, 连接断开, 节点消失, 锁就被释放了.
如果自己没有获取到锁, 就等待, 一直监听节点是否消失,锁被释放后, 再重新执行抢夺锁的操作.
集群选主
集群选主使用的是zookeeper的临时节点.
需求: 在集群中, 很多情况下是要区分主从节点的, 一般情况下主节点负责数据写入, 从节点负责数据读取, 那么问题来了, 怎么确定哪一个节点是主节点的, 当一个主节点宕机的时候, 其他从节点怎么再来选出一个主节点呢?
实现:
使用Zookeeper的临时节点可以轻松实现这一需求
我们把上面描述的这个过程称为集群选主的过程, 首先所有的节点都认为是从节点, 都有机会称为主节点, 然后开始选主, 步骤比较简单
- 所有参与选主的主机都去Zookeeper上创建同一个临时节点,那么最终一定只有一个客户端请求能够 创建成功(因为zookeeper的特性,同一层级目录下,节点的唯一性)。
- 成功创建节点的客户端所在的机器就成为了Master,其他没有成功创建该节点的客户端,成为从节点
- 所有的从节点都会在主节点上注册一个子节点变更的Watcher,用于监控当前主节点是否存活,一旦 发现当前的主节点挂了,那么其他客户端将会重新进行选主。
统一命名服务
统一命名服务使用的是ZK的node节点全局唯一的这个特点.
- 在分布式环境下,经常需要对应用/服务进行统一命名,便于识别。例如:IP不容易记住,而域名容易记住。创建一个节点后, 节点的路径就是全局唯一的, 可以作为全局名称使用.
统一配置管理
统一配置管理, 使用的是Zookeeper的watch机制
需求: 分布式环境下, 要求所有节点的配置信息是一致的, 比如Kafka集群. 对配置文件修改后, 希望能够快速同步到各个节点上.
方案: 可以把所有的配置都放在一个配置中心, 然后各个服务分别去监听配置中心, 一旦发现里面的内容发生变化, 立即获取变化的内容, 然后更新本地配置即可.
实现: 配置管理可交由Zookeeper实现
- 可将配置信息写入Zookeeper上的一个Znode.
- 各个客户端服务器监听这个Znode.
- 一旦Znode中的数据被修改, Zookeeper将通知各个客户端服务器.
统一集群管理
统一集群管理使用的是Zookeeper的watch机制
需求: 分布式环境中, 实时掌握每个节点的状态是必要的, 可以根据节点实时状态做出一些调整.
方案: Zookeeper可以实现实时监控节点状态变化
- 可将节点信息写入Zookeeper上的一个Znode.
- 监听这个Znode可获取它的实时状态变化.
三、Apache Dubbo集成zookeeper实现服务注册
在远程rpc通信过程中,有两个比较尖锐的问题
服务动态上下线的感知
负载均衡
实现步骤
1.引入zookeeper相关依赖
2.修改配置文件,注册地址为zookeeper服务器地址即可
实现原理
处理url是临时节点(好处是当注册该节点的服务器下线了,那么这个url就会被zookeeper从服务器上移除),其他都是持久化节点。providers表示服务的提供者,consumers表示服务的消费者。
当Dubbo服务消费启动时,会对providers节点下的子节点注册watcher监听,便于感知服务提供方节点上下线的变化,从而防止请求发送到已下线的服务发生失败。同时也会在/consumers下写消费者的url。这样做的好处有:
1.可以在监控平台看到dubbo服务正在被哪些服务调用
2.最重要的是消费者如果要调用服务,那么它回去/providers中通过负载均衡策略选择出提供方的url
整体来看都是运用到了zookeeper的临时节点、watcher等。除此之外Dubbo还可以针对不同情况实现一下功能
1.基于临时节点特性,服务提供者下线之后,注册中心回自动删除提供者的信息
2.注册中心重启后,Dubbo能自动恢复注册与请求
3.为了确保节点安全,zookeeper提供了acl权限控制
四、Apache Dubbo的高级应用
集群容错
1、Failover Cluster(默认)
失败自动切换,当出现失败,重试其它服务器。
通常用于读操作,但重试会带来更长延迟。
2、Failfast Cluster
快速失败,只发起一次调用,失败立即报错。
通常用于非幂等性的写操作,比如新增记录。
3、Failsafe Cluster
失败安全,出现异常时,直接忽略。
通常用于写入审计日志等操作。
4、Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。
通常用于消息通知操作。
5、Forking Cluster
并行调用多个服务器,只要一个成功即返回。
通常用于实时性要求较高的读操作,但需要浪费更多服务资源。
配置方式
负载均衡
- Random LoadBalance(随机,按照权重的设置随机概率 )默认
- RoundRobinLoadBalance(轮询,按照权重设置轮询比率)
- LeastActive LoadBalance(最少活跃数,响应快的提供者接受越多请求,响应慢的接受越少请求)
- ConsistentHashLoadBalance(一致性Hash,相同参数的请求总是发到同一个服务提供者(相同参数默认是指请求的第一个参数)根据服务提供者ip设置hash环,携带相同的参数总是发送的同一个服务提供者,若服务挂了,则会基于虚拟节点平摊到其他提供者上
配置方式
服务降级
Dubbo提供了mock机制来实现服务的降级,也就是说当服务的提供方发生异常时,客户端不抛出异常,而是执行兜底的逻辑
配置方式
主机绑定规则
主机绑定指的是dubbo服务对外暴露的Ip地址
第一步:查找环境变量DOUBBO_IP_TO_BIND属性配置的ip地址
第二步:从配置文件中获取host,检验host是否合理,如果合理,则直接返回。反之,进行下一步的获取。
第三步:获取本地ip地址,检验是否合理,如果合理,则直接返回。反之,进行下一步的获取。
第四步:利用注册中心去获取,首先判断注册中心地址是不是不为空,如果不为空,循环每个注册中心(dubbo支持多注册中心),通过socket去连接对应的注册中心地址,连接成功后,再通过socket获取本地ip地址。检验是否合理,如果合理,则直接返回。反之,进行下一步的获取。
第五步(最后一步):遍历本地网卡,返回第一个合理的ip地址。
在etc/host中配置机器名对应的ip地址映射
在环境变量中添加DOUBBO_IP_TO_BIND或者DOUBBO_IP_TO_REGISTRY,value为绑定的主机名
通过dubbo.protocol.host设置主机地址
针对不同协议提供了不同的端口号
Dubbo默认协议端口号:20880
Webservice协议端口号:80