Dubbo
分布式、高性能、透明化的RPC框架
RPC
远程过程调用协议
客户端通过互联网远程调用服务器,但是不知道服务器的具体实现,只知道远程服务提供的功能。最大的优点:数据安全性。也可以使用HTTP请求,但是可能会比较慢,而且一些优化做的并不好。
SOA
面向服务框架
SOA是一种设计思想,将各个业务分成各个功能服务,各个服务又可以通过协调合作提供一系列的功能。另外这些服务还各自独立地放在自己的操作系统中,之间的通信只能通过网络的方式来进行而不是通过进程的方式。
三大功能
面向接口远程方法调用、集群容错和负载均衡、服务的自动注册与发现。
远程调用:提供多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
集群容错:提供负载均衡、失败容错、地址路由、动态配置等集群的支持。
服务注册与发现:基于注册中心目录服务,使消费者能够动态的查找服务方的接口,使地址透明,使服务方能够平滑地增加或者减少机器。
优点
服务链路生成:服务越来越多的时候,dubbo能够解决服务之间如何调用。
负载均衡:服务部署在不同的机器,根据机器的处理状况动态调用服务。
资源调度和治理:基于访问压力实时管理集群容量,提高集群的销量。
服务降级:当某个服务挂了之后,选择备用服务。
分布式:把整个系统拆分成不同的功能放在不同的服务器中独立运行,来减轻单体服务的压力提高并发和性能。比如电商系统可以拆成:订单系统、商品系统、登录系统等。
结构、流程
结构
Provider :提供者,服务发布方.
Consumer:消费者, 调用服务方
Container:Dubbo容器.依赖于Spring容器.
Registry: 注册中心.当Container启动时把所有可以提供的服务列表上Registry中进行注册.作用:告诉Consumer提供了什么服务和服务方在哪里.
Monitor:监听器
虚线都是异步访问,实线都是同步访问
蓝色虚线:在启动时完成的功能
红色虚线(实线)都是程序运行过程中执行的功能
过程
0 启动容器,相当于在启动Dubbo的Provider
1 启动后会去注册中心进行注册.注册所有可以提供的服务列表
2 在Consumer启动后会去Registry中获取服务列表和Provider的地址.进行订阅.
3 当Provider有修改后,注册中心会把消息推送给Consummer
3.1 使用了观察者设计模式(又叫发布/订阅设计模式)
4 根据获取到的Provider地址,真实调用Provider中功能.
4.1 在Consumer方使用了代理设计模式.创建一个Provider方类的一个代理对象.通过代理对象获取Provider中真实功能,起到保护Provider真实功能的作用.
5 Consumer和Provider每隔1分钟向Monitor发送统计信息,统计信息包含,访问次数,频率等.
总结
注册中心、服务提供者、消费者三者间的链接均为长连接,监控中心除外。
注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心立即推送时间通知消费者。
负载均衡策略
random LoadBalance
(默认,基于权重的随机负载均衡机制)
RoundRobin LoadBalance
(不推荐,基于权重的轮询负载均衡策略)
轮询,按照公约后的权重设置轮询比率。
存在慢的服务者累积请求问题,比如:第二台机器很慢,但是没挂,当请求调到第二台那里就卡住,慢慢的所有的请求就都卡那里了。
LeastActive LoadBalance
最少活跃数,相同活跃数随机。活跃数指调用数-完成数。
慢的服务者受收到的请求更少
consistentHash loadBalance
一致Hash,相同参数总是发到同一个服务者。(如果你要把一类请求放到一个节点)
当一个服务者挂了之后,原本的请求基于虚拟节点平摊给另外的提供者。
配置
服务端服务级别 <dubbo:service interface="..." loadbalance="roundrobin" /> 客户端服务级别 <dubbo:reference interface="..." loadbalance="roundrobin" /> 服务端方法级别 <dubbo:service interface="..."> <dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:service> 客户端方法级别 <dubbo:reference interface="..."> <dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:reference>
注解配置方式: 消费方基于基于注解的服务级别配置方式: @Reference(loadbalance = "roundrobin") HelloService helloService;
RPC调用过程
1. 服务消费方(client)调用,以本地调用方式调用服务;
2. client stub(存根)接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
3. client stub找到服务地址,并将消息发送到服务端;
4. server stub收到消息后进行解码;
5. server stub根据解码结果调用本地的服务;
6. 本地服务执行并将结果返回给server stub;
7. server stub将返回结果打包成消息并发送至消费方;
8. client stub接收到消息,并进行解码;
9. 服务消费方得到最终结果。
dubbo和zookeeper
zookeeper和dubbo 实现负载均衡
ZooKeeper会维护一个树形的数据结构,类似于Windows资源管理器目录,其中ephemeral类型的节点会随着创建它的客户端断开而被删除,利用这个特性很容易实现软负载均衡。
基本原理是,每个应用的Server启动时创建一个ephemeral节点,应用客户端通过读取节点列表获得可用服务器列表,并订阅节点事件,有Server宕机断开时触发事件,客户端监测到后把该Server从可用列表中删除。
dubbo的健壮性表现
1. 监控中心宕掉不影响使用,只是丢失部分采样数据
2. 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
3. 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
4. 注册中心全部宕掉后,已经注册了的服务提供者和服务消费者仍能通过本地缓存通讯
5. 服务提供者无状态,任意一台宕掉后,不影响使用
6. 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
我们前面提到过:注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。所以,我们可以完全可以绕过注册中心——采用 dubbo 直连 ,即在服务消费方配置服务提供方的位置信息。
xml配置方式: <dubbo:reference id="userService" interface="com.zang.gmall.service.UserService" url="dubbo://localhost:20880" />