Dubbo(二)Dubbo和ZooKeeper的协同工作原理

Dubbo和ZooKeeper是如何协同工作的?

文章目录

Dubbo

  • 通过RPC的方式实现服务调用

  • 通过简单实现理解原理:

    Client和Server共用一个接口,将接口打成一个jar包,在客户端和服务端引入这个jar包,Client端面向接口写调用,Server端面向接口写实现,中间的网络通信交给Dubbo框架去实现。

以下是黄字叙述内容:“点对点RPC”的实现细节

1.服务提供者-配置

<!--1.当前项目在整个分布式架构里面的唯一名称,用于计算依赖关系 -->
<dubbo:application name="dubbo-provider"/>

<!--2.定义协议端口-->
<dubbo:protocol port="28800"/>

<!--3.定义注册中心的地址-->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>

<!--4.服务发布的配置,需要暴露的服务接口-->
<bean id="userService" class="com.duan.service.impl.UserServiceImpl"/>
<dubbo:service interface="com.duan.service.IUserService" ref="userService"/>

加载Spring配置

public class Provider {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml");
        context.start();
        System.in.read(); // 按任意键退出
    }
}

2.服务消费者-配置

<!--消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="dubbo-consumer"/>

<!--定义注册中心的地址-->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>

<!--生成远程服务代理-->
<dubbo:reference interface="com.duan.service.IUserService" id="userService"/>

加载Spring配置,并调用远程服务

public class Consumer {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
        context.start();
        // 获取远程服务代理
        DemoService userService = (DemoService)context.getBean("userService");
        // 执行远程方法
        String hello = userService.sayHello("world");
        // Hello world
        System.out.println( hello );
    }
}

负载均衡

以上就是典型的点对点的服务调用,假如在未指定zookeeper注册中心时,Client和Server端的配置文件部分如下

<!--dubbo这个服务所要暴露的服务地址所对应的注册中心,N/A为不使用注册中心-->
<dubbo:registry address="N/A"/>

此时,若我们为了高可用,可以:

  • 配置多个服务提供者;
  • consumer.xml中配置多个服务调用者,在<dubbo:reference>标签的url属性中加入多个地址,中间用分号隔开即可配置负载均衡策略在consumer.xml的dubbo:reference标签中增加loadbalance属性即可,属性值可以为如下四种:
1. 随机 + 权重(random)
  1. 计算服务Provider的总权重,并维护一个前缀和数组;
  2. 基于第一步的结果,在0~总权重 之间生成一个随机数;
  3. 随机数得到一个权重,遍历前缀和数组,找到第一个比随机权重大的位置,即可确定选择的服务Provider;
  4. 如果所有服务提供者节点都没有分配权重,或者分配的权重都一样,那么就采用随机的选择一个服务提供者节点;
2.轮询 + 权重(roundrobin)
  1. 计算服务提供者的总权重。
  2. 每个服务提供者除了始终不变的固定权重以外,需要记录服务提供者当前权重。
  3. 每次请求,更新所有的服务提供者的当前权重,当前权重 = 当前权重 + 固定权重。
  4. 从上一步得到的结果中,选择一个当前权重最大的服务提供者用于处理请求,如果存在多个,那么就看遍历的过程中先遇到哪个服务提供者就是哪一个。并且,选中的权重最大的服务提供者更新其当前权重 = 当前权重 - 总权重
3.最少连接(leastactive)
  1. Client存在一个计数器,记录当前通过某个Server提供者的请求还未完成的总数;
  2. 选择计数最少的那个用于处理当前请求, 将计数器+1;
  3. 如果存在多个相同的计数,那么使用随机+权重的方式选取;
  4. 否则从多个最少的服务提供者当中随机的选择一个处理当前请求;
4.一致性Hash(ConsistentHash)

一致性Hash,相同参数的请求总是发到同一提供者;

consumer.xml中生成接口的远程代理如下:

<dubbo:reference id="demoService" interface="com.st.DemoService"
                 url="dubbo://192.168.11.1:20880/com.st.DemoService;
                      dubbo://192.168.11.2:20880/com.st.DemoService;
                      dubbo://192.168.11.3:20880/com.st.DemoService"
                 loadbalance="roundrobin"/>

现在整体架构如下图(假设consumer为订单服务,provider为用户服务)

图解Dubbo和ZooKeeper是如何协同工作的?

此时会有什么问题?

  1. 当服务器增加服务节点时,需要修改配置文件;
  2. 当其中一个服务Provider宕机时,consumer不能及时感知到,还会往宕机的服务发送请求;

这是后就需要引入zookeeper注册中心了!

ZooKeeper注册中心

zookeeper注册中心实现注册的大致流程如下图:

图解Dubbo和ZooKeeper是如何协同工作的?

对照上图来看Dubbo官网上的Dubbo框架图,是不是觉得和上图很类似?zookeeper是被选来作为Dubbo框架中的注册中心。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pwYKV8qn-1650879464231)(https://dubbo.apache.org/imgs/architecture.png)]

节点

角色说明

Provider

暴露服务的服务提供方

Consumer

调用远程服务的服务消费方

Register

服务注册与发现的注册中心

Monitor

统计服务的调用次数和调用时间的监控中心

Container

服务运行容器

调用关系说明

  • Container负责启动(上面的容器为Spring容器),加载,运行服务提供者;
  • 服务提供者在启动时,向注册中心注册自己提供的服务;
  • 服务消费者在启动时,向注册中心订阅自己所需的服务;
  • 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者;
  • 服务消费者,从提供者地址列表中,基于软负载均衡算法,选择一台提供者进行调用,如果调用失败,再选另一个台调用;
  • 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

回归之前的问题,如要使用注册中心,只需要将provider.xml和consumer.xml恢复为如下:

<!--<dubbo:registry address="N/A"/>-->
<dubbo:registry protocol="zookeeper" address="192.168.11.129:2181"/>

如果zookeeper是一个集群,则多个地址之间逗号分隔即可:

<dubbo:registry protocol="zookeeper" address="192.168.11.129:2181,192.168.11.137:2181,192.168.11.138:2181"/>

将consumer.xml中配置的直连的方式去掉

<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<!--<dubbo:reference id="demoService" interface="com.st.DemoService"-->
<!--url="dubbo://localhost:20880/com.st.DemoService"/>-->

启动上述服务后,我们观察在zookeeper的根节点多了一个dubbo节点,如下图(树状存储)

图解Dubbo和ZooKeeper是如何协同工作的?

最后一个节点中192.168.1.104是我的内网地址,绿色代表临时节点,而其他节点是持久节点,这样,当服务宕机时,这个节点就会自动消失,不在提供服务,服务消费者也不会载请求。若部署多个Service,则Provider下面会有好几个节点,一个节点保存一个Service的服务地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值