目录

一、如何理解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的临时节点可以轻松实现这一需求

我们把上面描述的这个过程称为集群选主的过程, 首先所有的节点都认为是从节点, 都有机会称为主节点, 然后开始选主, 步骤比较简单

  1. 所有参与选主的主机都去Zookeeper上创建同一个临时节点,那么最终一定只有一个客户端请求能够 创建成功(因为zookeeper的特性,同一层级目录下,节点的唯一性)。
  2. 成功创建节点的客户端所在的机器就成为了Master,其他没有成功创建该节点的客户端,成为从节点
  3. 所有的从节点都会在主节点上注册一个子节点变更的Watcher,用于监控当前主节点是否存活,一旦 发现当前的主节点挂了,那么其他客户端将会重新进行选主。

统一命名服务

统一命名服务使用的是ZK的node节点全局唯一的这个特点.

  • 在分布式环境下,经常需要对应用/服务进行统一命名,便于识别。例如:IP不容易记住,而域名容易记住。创建一个节点后, 节点的路径就是全局唯一的, 可以作为全局名称使用.

统一配置管理

统一配置管理, 使用的是Zookeeper的watch机制

需求: 分布式环境下, 要求所有节点的配置信息是一致的, 比如Kafka集群. 对配置文件修改后, 希望能够快速同步到各个节点上.

方案: 可以把所有的配置都放在一个配置中心, 然后各个服务分别去监听配置中心, 一旦发现里面的内容发生变化, 立即获取变化的内容, 然后更新本地配置即可.

实现: 配置管理可交由Zookeeper实现

  1. 可将配置信息写入Zookeeper上的一个Znode.
  2. 各个客户端服务器监听这个Znode.
  3. 一旦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

并行调用多个服务器,只要一个成功即返回。

通常用于实时性要求较高的读操作,但需要浪费更多服务资源。

配置方式

负载均衡

  1. Random LoadBalance(随机,按照权重的设置随机概率 )默认
  2. RoundRobinLoadBalance(轮询,按照权重设置轮询比率)
  3. LeastActive LoadBalance(最少活跃数,响应快的提供者接受越多请求,响应慢的接受越少请求)
  4. 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