大家好,我是猿人(猿码天地创始人),今天给码农们或即将成为码农或想成为码农的朋友讲讲Zookeeper最常用的作用,作为dubbo的注册中心,现在是深夜23:25分,猿人最擅长熬夜,就是不怕掉头发!一切都是为了亲爱的粉丝朋友能学到知识,猿人熬夜也是值得的!
我是「猿码天地」,一个热爱技术、热爱编程的IT猿。技术是开源的,知识是共享的!
写作是对自己学习的总结和记录,如果您对 Java、分布式、微服务、中间件、Spring Boot、Spring Cloud等技术感兴趣,可以关注我的动态,我们一起学习,一起成长!
用知识改变命运,让家人过上更好的生活,互联网人一家亲!
Java知识学堂:https://gitee.com/zhangbw666/it-knowledge
好,废话不多说,直接干,进入正题:Good Good Study,Day Day Up!
1. Dubbo是什么?
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架(告别Web Service模式中的WSdl,以服务者与消费者的方式在dubbo上注册) 其核心部分包含:
-
远程通讯
提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
-
集群容错
提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
-
自动发现
基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
2. Dubbo能做什么?
1.透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
2.软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
3. 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
Dubbo采用全spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。
3. Dubbo的架构
![](https://img-blog.csdnimg.cn/img_convert/99aa48c3c1aee4b1002727e7c672c318.png)
节点角色说明:
-
Provider: 暴露服务的服务提供方。
-
Consumer: 调用远程服务的服务消费方。
-
Registry: 服务注册与发现的注册中心。
-
Monitor: 统计服务的调用次数和调用时间的监控中心。
-
Container: 服务运行容器。
这点我觉得非常好,角色分明,可以根据每个节点角色的状态来确定该服务是否正常。
调用关系说明:
0. 服务容器负责启动,加载,运行服务提供者。
1. 服务提供者在启动时,向注册中心注册自己提供的服务。
2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
4. Zookeeper用作注册中心的原理
简单来讲,zookeeper可以充当一个服务注册表(Service Registry),让多个服务提供者形成一个集群,让服务消费者通过服务注册表获取具体的服务访问地址(ip+端口)去访问具体的服务提供者。
具体来说,zookeeper就是个分布式文件系统,每当一个服务提供者部署后都要将自己的服务注册到zookeeper的某一路径上。
在zookeeper中,进行服务注册,实际上就是在zookeeper中创建了一个znode节点,该节点存储了该服务的IP、端口、调用方式(协议、序列化方式)等。该节点承担着最重要的职责,它由服务提供者(发布服务时)创建,以供服务消费者获取节点中的信息,从而定位到服务提供者真正网络拓扑位置以及得知如何调用。RPC服务注册、发现过程简述如下:
1.服务提供者启动时,会将其服务名称,ip地址注册到注册中心。
2.服务消费者在第一次调用服务时,会通过注册中心找到相应的服务的IP地址列表,并缓存到本地,以供后续使用。当消费者调用服务时,不会再去请求注册中心,而是直接通过负载均衡算法从IP列表中取一个服务提供者的服务器调用服务。
3.当服务提供者的某台服务器宕机或下线时,相应的ip会从服务提供者IP列表中移除。同时,注册中心会将新的服务IP地址列表发送给服务消费者机器,缓存在消费者本机。
4.当某个服务的所有服务器都下线了,那么这个服务也就下线了。
5.同样,当服务提供者的某台服务器上线时,注册中心会将新的服务IP地址列表发送给服务消费者机器,缓存在消费者本机。
6.服务提供方可以根据服务消费者的数量来作为服务下线的依据。
架构
![](https://img-blog.csdnimg.cn/img_convert/f5db6974dcdcefb6cc4e4aba0291b532.png)
-
1 每个Server在内存中存储了一份数据;
-
2 Zookeeper启动时,将从实例中选举一个leader(Paxos协议);
-
3 Leader负责处理数据更新等操作(Zab协议);
-
4 一个更新操作成功,当且仅当大多数Server在内存中成功修改数据。
![](https://img-blog.csdnimg.cn/img_convert/09fde65feb508477d571b718bea10271.png)
感知服务的下线&上线
zookeeper提供了“心跳检测”功能,它会定时向各个服务提供者发送一个请求(实际上建立的是一个 socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其剔除。
服务消费者会去监听相应路径,一旦路径上的数据有任务变化(增加或减少),zookeeper都会通知服务消费方服务提供者地址列表已经发生改变,从而进行更新。
更为重要的是zookeeper 与生俱来的容错容灾能力
(比如leader选举),可以确保服务注册表的高可用性。
使用 zookeeper 作为注册中心时,客户端订阅服务时会向 zookeeper 注册自身;主要是方便对调用方进行统计、管理。但订阅时是否注册 client 不是必要行为,和不同的注册中心实现有关,例如使用 consul 时便没有注册。
5. Dubbo源码实战
Dubbo实战源码地址:https://gitee.com/zhangbw666/dubbo
项目介绍
dubbo 组件学习,完整的项目和详细的操作步骤
软件架构
dubbo-demo-api API
dubbo-demo-consumer 服务消费者
dubbo-demo-parent 父模块
dubbo-demo-provider-20880 服务提供者 端口 20880
dubbo-demo-provider-20881 服务提供者 端口 20881
模块说明
-
安装Dubbo服务注册中心(zookeeper) 下载 http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.12/ 解压,将文件放到磁盘,修改config下的zoo_sample.cfg为zoo.cfg,启动bin下的zkServer.cmd即可。
-
发布Dubbo服务 下载Demo https://github.com/alibaba/dubbo 参考dubbo-demo-provider-20880
-
Dubbo Admin管理控制台 将dubbo-admin-2.6.0.war包解压后放到tomcat ROOT目录,先启动注册中心zookeeper服务,再启动tomcat,启动成功后访问:http://localhost:8080/ 用户名/密码:root/root
-
消费Dubbo服务 远程调用服务 参考 dubbo-demo-consumer 用法:先启动zookeeper服务注册中心,再启动tomcat dubbo admin管理控制台,然后启动 服务提供者dubbo-demo-provider-20880(测试类),在管理控制台查看是否启动成功,启动成功后再启动服务消费者dubbo-demo-consumer(测试类)
-
接口抽取及依赖版本统一 新建dubbo-demo-api 抽取ProviderService接口/新建dubbo-demo-parent实现依赖版本统一管理。
-
Dubbo服务集群实现负载均衡 新建dubbo-demo-provider-20881 复制dubbo-demo-provider-20880工程 改下端口就行。
dubbo-demo-provider.xml文件
<!-- 使用dubbo协议,在20881端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20881"/>
ProviderServiceImpl.java文件
public class ProviderServiceImpl implements ProviderService {
public String sayHello(String name) {
return "服务001(端口:20881)"+name;
}
}
ProviderTest20881.java文件
public class ProviderTest20881 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"dubbo-demo-provider.xml"});
context.start();
System.out.println("服务提供者向zookeeper注册中心注册服务成功(端口:20881)");
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
context.close();
}
}
用法:先启动zookeeper服务注册中心,再启动tomcat dubbo admin管理控制台,然后启动服务提供者dubbo-demo-provider-20880(测试类) 和dubbo-demo-provider-20881(测试类),在管理控制台查看是否启动成功,启动成功后再启动服务消费者dubbo-demo-consumer(测试类),在控制台查看每次消费者调用哪一个提供者,达到负载均衡的目的。
猿人于2021年3月16日 0点40分 于深圳整理,整理完这篇文章头发还有10万零546根,今天掉了1根头发,持续记录头发根数,加油!