RPC框架之Dubbo

问题1:为什么要把系统拆分成分布式的?为啥要用dubbo?

1.为什么要将系统进行拆分?

  1. 要是不拆分系统,一个大系统几十万行代码,很多人共同维护一份代码,简直是悲剧;
  2. 拆分了以后,一个大系统拆分成很多小服务,平均每个系统也就几万行代码,每个服务部署到单独的机器

2.如何进行服务拆分?

? 大部分系统,是要进行多轮拆分的,第一次拆分就可能将原来的多个模块拆分开来。

? 但是后来可能每个系统都变得很复杂了,每个模块拆分出来的服务又要继续拆分。

3.拆分后可以不用dubbo吗?

? 当然可以,大不了各个系统之间,直接基于springmvc,就通过纯httpj接口互相通信。但是这里肯定是由问题的,因为HTTP接口通信维护起来成本很高,要考虑超时重试,负载均衡等各种问题。

所以dubbo说白了,就是一个rpc框架,就是本地就是进行接口调用,但是dubbo会代理这个调用请求,跟远程机器网络通信,处理负载均衡,服务上下线自动感知,超时重试等问题,就不用我们自己做,交给dubbo。

?

问题2:说一下dubbo的工作原理,注册中心挂了可以继续通信吗?说一下一次rpc请求的流程?

1.dubbo工作原理

2.dubbo分层

  • 第一层:service层,需要服务提供方和消费方来实现
  • 第二层:config层,配置层,主要是对dubbo的各种配置
  • 第三层:proxy层,服务代理层,透明生成客户端的stub和服务端的skeleton
  • 第四层:registry层,服务端的注册与发现
  • 第五层:cluster层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
  • 第六层:monitor层,监控层,对rpc接口的调用次数和调用时间进行监控
  • 第七层:protocol层,远程调用层,封装rpc调用
  • 第八层:exchange层,信息交换层,封装请求响应模式,同步转异步
  • 第九层:transport层,网络传输层,抽象mina和netty为统一接口
  • 第十层:serilize层,数据序列化层

2.注册中心挂了可以继续通信吗?

是可以的,因为客户端第一次从注册中心获取服务端的服务后,会缓存在自己本地,下一次调用服务端不用去请求注册中心,因此注册中心挂了是可以继续通信的

问题3:dubbo都支持哪些通信协议和序列化协议

1.dubbo支持不同的协议

  1. dubbo协议

    默认就是走dubbo协议,单一长链接,NIO异步通信

    (NIO通信原理:NIO采用了Reactor模式(类似于观察者模式,不同之处在于Reactor模式可以监听多个主题),通过一个多路复用器来监听多个客户端的网络句柄,一旦监听到客户端的请求消息,将对应的请求消息转发给对应的Handler(业务处理类))

    适合场景:传输数据量较小,但是并发很高

  2. rmi协议

    走java二进制序列化,多个短连接,适合消费者和提供者数量差不多,适用于文件的传输,一般较少

  3. hessian协议

    走hessian序列化协议,多个短连接,适用于提供者数量和消费者数量还多,适用于文件传输,一般较少使用

  4. http协议

    走json序列化

  5. webservice

    走soap文本序列化

问题4:dobbo负载均衡策略和集群容错策略?动态代理策略?

dobbo负载均衡策略

1.random loadbalance

默认情况下,dubbo是random load balcance 随机调用实现负载均衡,可以对provider不同的实例设置不同的权限,会按照权重来负载均衡,权重越大分配流量越高,一般就用这个默认的就可以了。

2.roundrobin loadbalance

这个默认就是均匀地将流量打到各个机器上去,但是如果各个机器的性能都不一样,容易导致性能差的机器负载过高而宕机。此时需要调整权重,让性能差一点的机器承载权重少一些

3.leastactive loadbalance

这个就是自动感知一下,如果某个机器性能差,那么接收的请求越少,约不活跃,此时就会给不活跃的性能差的机器更少的请求

4.consistanthash loadbalance

一致性hash算法,相同的参数的请求一定分配到一个provider上去,provider挂掉的时候,会基于虚拟节点均匀分配剩余的流量,抖动不会太大。如果需要的不是随机负载均衡,是要一类请求都到这个节点上,那就走这个一致性hash策略

dobbo集群容错策略

1.failover cluster模式

? 失败自动切换,自动重试其他机器,dubbo默认使用这种策略

2.failfast cluster模式

一次失败就立即失败,常见于写操作

3.failsafe cluster模式

出现异常就忽略,常用于不重要的接口调用,比如日志记录

4.failbackc cluster模式

失败了后台自动记录请求,然后定时发送,比较适合消息队列这种情况

5.focking cluster模式

并行的调用多个provider,只要一个成功就立即返回

6.broadcast cluster模式

逐个调用所有的provider

dubbo的动态代理策略

默认使用 javassist动态字节码生成,创建代理类

问题5:你了不了解spi机制呢?如何基于spi机制对dubbo进行扩展?

SPI机制

  • 简单来说,就是service provider interface;比如有一个接口A,现在这个接口A有三个实现类,那么在运行的时候对接口到底用哪个实现类呢?这就需要SPI,需要根据指定的配置和默认的配置,去找到对应的实现类加载进来,然后用这个实现类的对象

    例如:接口A --> 实现类A1 实现类A2 实现类A3

    配置一下,接口A= 实现类A2

    在系统运行的时候,会加载这个配置,用实现类A2实例化出对象来提供服务

    • 比如说你有一个工程Demo ,里面有一个接口A,接口A在工程里是没有实现的--> 系统在运行的时候,怎么给接口A选择一个实现类呢?
    • 你就可以自己搞一个jar包,META-INF/services/,上放一个文件,文件名就是接口名,接口A,接口A的实现类=com.ultrapower.service.实现类A2.让工程A来依赖这个jar包,然后在系统运行的时候,工程跑起来,对接口A,就会扫描自己依赖的所有jar包,在每个jar包里找找,有没有 META-INF/service 文件夹?如果有,在里面找,有没有接口A这个名字的文件?如果有,在里面找找有没有接口A的实现类是你的jar包里的那个类

Dubbo的SPI机制

dubbo也用了spi的思想,不过没有用到jdk的spi机制,是自己实现的一套SPI机制

   1 Protocol protocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension()   
  • Protocol接口,dubbo需要判断一下,在系统运行的时候,应该选用这个Protocol接口的哪个实现类来实例化对象来使用呢?
  • 他会去找一个你配置的Protocol,它就会将你配置的Protocol实现类,加载到 jvm中来,然后会实例化对象,就会用到你提供的哪个Protocol接口实现类
  • 微内核,可插拔,大量的组件,Protocol负责RPC调用,你可以实现自己的rpc调用组件,实现Protocol接口,给自己一个实现类即可
  • 这行代码就是Dubbo中大量使用的,就是对很多组件,都保留一个接口和多个实现,然后在运行的时候动态的根据配置去找对应的实现类,如果没有配置,那就走默认的实现类。

?

 1
 2   @SPI("dubbo")
 3   public interface Protocol{
 4        /**
 5        * 获取缺省端口,当用户没有配置端口时使用。
 6        *
 7        * @return 缺省端口
 8        */
 9       int getDefaultPort();
10   ?
11       /**
12        * 暴露远程服务:<br>
13        * 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();<br>
14        * 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。<br>
15        * 3. export()传入的Invoker由框架实现并传入,协议不需要关心。<br>
16        *
17        * @param <T>     服务的类型
18        * @param invoker 服务的执行体
19        * @return exporter 暴露服务的引用,用于取消暴露
20        * @throws RpcException 当暴露服务出错时抛出,比如端口已占用
21        */
22       @Adaptive
23       <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
24   ?
25       /**
26        * 引用远程服务:<br>
27        * 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,协议需相应执行同URL远端export()传入的Invoker对象的invoke()方法。<br>
28        * 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。<br>
29        * 3. 当url中有设置check=false时,连接失败不能抛出异常,并内部自动恢复。<br>
30        *
31        * @param <T>  服务的类型
32        * @param type 服务的类型
33        * @param url  远程服务的URL地址
34        * @return invoker 服务的本地代理
35        * @throws RpcException 当连接服务提供方失败时抛出
36        */
37       @Adaptive
38       <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
39   ?
40       /**
41        * 释放协议:<br>
42        * 1. 取消该协议所有已经暴露和引用的服务。<br>
43        * 2. 释放协议所占用的所有资源,比如连接和端口。<br>
44        * 3. 协议在释放后,依然能暴露和引用新的服务。<br>
45        */
46       void destroy();
47   ?
48   }

在dubbo自己的jar里,在META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol文件中

dubbo=com.alibaba.dubbo.rpc.DubboProtocol

http=com.alibaba.dubbo.rpc.HttpProtocol

hessian=com.alibaba.dubbo.rpc.hessianProtocol

所有说这里就是dubbo默认的配置,其实就是一个Protocol接口,@SPI("dubbo")说的就是,通过SPI机制来提供实现类,实现类是通过dubbo作为默认key去配置文件里找的,配置文件的名称和接口名的全路径名时一样的,通过dubbo作为key 可以找到默认的实现类就是 com.alibaba.dubbo.rpc.DubboProtocol

dubbo默认的网络通信协议,就是dubbo协议,用的 DubboProtocol

如果想要动态替换默认的实现类,需要使用@Adapter接口,Protocol接口中,有两个方法加了@Adapter注解,就是说那俩接口会被代理实现。

比如:这个Protocol接口搞了俩@Adapter 注解标注了方法,在运行的时候,就会针对Protocol生成代理类,这个代理类的俩方法里面会代理代码,代理代码会在运行时候动态根据url中的protocol来获取那个key,默认是dubbo,你也可以自己指定别的key,那么就会获取别的实现类的实例了。

通过这个URL的参数不同,就可以控制动态的使用不同的组件实现类

问题6:如何基于dubbo做服务治理,服务降级,失败重试以及超时重试?

1.服务治理

1.调用链路生成

一个大型的分布式系统,由大量的服务组成。这些服务之间是如何调用的呢?调用链路是啥?

那就需要基于dubbo做的分布式系统中,对各个服务之间的调用自动记录下来,然后自动将各个服务的依赖关系和调用链路生成出来,做成一张图,大家可以看到的

2.服务访问压力以及时长统计

需要自动统计各个接口之间的访问次数和调用延迟,而且要分成两个级别。一个级别是接口粒度,就是每个服务额每个接口每天被调用的次数,TP50 ,TP90,TP99,三个档次的请求延迟分别是多少;第二个级别是从源头入口,一个完整的请求链路经过几十个服务之后,完成一次请求,每天全链路走多少次,全链路请求延迟的TP50,TP90,TP99

分别是多少?

这些东西都搞定以后,后面才看当前系统的压力到底在哪里?如何来扩容和优化?

3.其他的

服务分层(避免循环依赖),调用链路失败监控和报警,服务鉴权,每个服务 的可用性的监控

2.服务降级

比如服务A调用服务B,结果服务B挂掉了,服务A重试几次调用服务B,还是不行,直接降级,走一个备用逻辑,给用户返回响应

?

问题7:分布式服务接口的幂等性如何设计?

所谓幂等性,就是说一个接口,多次发起同一个请求,你这个接口得保证结果是准确的,比如不能多扣款,不能多插入一条数据,不能将统计值多加1。这就是幂等性。

保证幂等性的手段如下:

  • 对于每次请求必须有一个全局唯一的标识
  • 每次处理完请求后,必须有一个记录标识这个请求处理完了,比如常见的方案是在mysql 中记录个啥状态,比如支付之前记录一条这个订单的支付流水,而且支付流水采用orderid 作为 唯一键。只有成功插入这个支付流水,才可以执行实际的支付扣款。
  • 每次接收到了请求需要进行判断之前是否处理过的逻辑处理,比如说吗,如果有一个订单已经支付了,就已经有一个支付流水了,那么如果重复发送请求,则此时先插入支付流水,然而orderid已经存在了,唯一键约束生效,报错插入失败,然后你就不用扣款了
  • 一般生产上可以用redis中的 set来保证幂等

问题8:如何设计一个类似于Dubbo的rpc框架

简单梳理一下思路:

  1. 上来就要把服务到注册中心注册,就应该有一个注册中心,保留各个服务的地址信息,就可以用zookeeper来做。
  2. 然后消费者要去注册中心去拿服务信息,每个服务可能会存在于有多台机器
  3. 接着你就该发起一次请求,如何发呢? 基于动态代理,面向接口获取到一个动态代理,这个动态代理就是本地接口的一个代理,然后这个代理会找到服务对应的机器地址
  4. 然后找哪台机器发送请求? 这里会有一个负载均衡算法,比如可以使用随机轮训的算法
  5. 找到一台机器,如何发送给他? 可以用netty,nio的方式,第二个问题发送什么格式?可以是序列化格式或者json格式等
  6. 服务起那边一样,需要针对你的服务生成一个动态代理,监听某个网络端口,然后代理你本地的服务代码,接收到请求,就代理本地的服务方法。

原文地址:https://www.cnblogs.com/ft-greate/p/12355290.html

时间: 2024-12-16 06:48:16

RPC框架之Dubbo的相关文章

RPC框架与Dubbo完整使用

这并不是原理性的解释文章.而是快速入门,还有一个完整的Java例子. 一篇我觉得不错的文章推荐:深入浅出 RPC - 浅出篇 一.RPC 什么是RPC? RPC(Remote Procedure Call)远程过程调用.见名知意 - 从远程主机调用一个过程/函数. RPC的目标是:使得程序调用其它远程主机上的函数,好像调用本程序内的函数一样简单.并且屏蔽编程语言的差异性. 要实现上述目标,首先的是设计一种通讯协议,所以RPC还代表着这一类协议(Protocol) RPC不是一个具体的协议,而是一

自己动手写RPC框架到dubbo的服务动态注册,服务路由,负载均衡功能实现

RPC即远程过程调用,它的实现方式有很多,比如webservice等.框架调多了,烦了,没激情了,我们就该问自己,这些框架的作用到底是什么,来找回当初的激情. 一般来说,我们写的系统就是一个单机系统,一个web服务器一个数据库服务,但是当这单台服务器的处理能力受硬件成本的限制,是不能无限的提升处理性能的.这个时候我们使用RPC将原来的本地调用转变为调用远端的服务器上的方法,给系统的处理能力和吞吐量带来了提升. RPC的实现包括客户端和服务端,即服务的调用方和服务的提供方.服务调用方发送rpc请求

RPC原来就是socket——RPC框架到dubbo的服务动态注册,服务路由,负载均衡演化

序:RPC就是使用socket告诉服务端我要调你的哪一个类的哪一个方法然后获得处理的结果.服务注册和路由就是借助第三方存储介质存储服务信息让服务消费者调用. RPC即远程过程调用,它的实现方式有很多,比如webservice等.框架调多了,烦了,没激情了,我们就该问自己,这些框架的作用到底是什么,来找回当初的激情. 一般来说,我们写的系统就是一个单机系统,一个web服务器一个数据库服务,但是当这单台服务器的处理能力受硬件成本的限制,是不能无限的提升处理性能的.这个时候我们使用RPC将原来的本地调

一个入门rpc框架的学习

一个入门rpc框架的学习 参考 huangyong-rpc 轻量级分布式RPC框架 该程序是一个短连接的rpc实现 简介 RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. RPC 可基于 HTTP 或 TCP 协议,Web Service 就是基于 HTTP 协议的 RPC, 它具有良好的跨平台性,但其性能却不如基于 TCP 协议的 RPC.会两方面会直接影响 RPC 的性能,一是传输方式,二是序列化. 众所

使用Dubbo、JSF等RPC框架时,对于异常的处理

无论是Dubbo还是JSF等RPC框架,一般都会把接口分为2部分: 1,服务端(provider) 2,客户端(consumer) 由于,客户端与服务端可能不在同一个应用中,所以客户端一般在调用服务端的接口时,通常会返回一个结果实体,来标明这一次请求操作是否成功. 例如: public class BaseResultDto<T> { /** * 是否操作成功 */ private boolean success; /** * 提示信息 */ private String msg; /** *

Netty自娱自乐之类Dubbo RPC 框架设计构想 【上篇】

之前在前一篇的<Netty自娱自乐之协议栈设计>,菜鸟我已经自娱自乐了设计协议栈,gitHub地址为https://github.com/vOoT/ncustomer-protocal.先这一篇中,准备接着自娱去实现一个RPC框架,现在公司共的是Dubbo,那么先不看其代码,先自行实现一下吧. dubbo 包括 注册和服务调用,细节我们先不管,然后,我先先实现一个如下的简单模型 哈哈哈,第一个版本就是这么简单,粗暴.说到自定义配置,首先想到的是Spring 自定义标签,利用标签进行配置服务.而

RPC框架Dubbo分析

1,背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进 单一应用架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本 此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键 垂直应用架构 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率 此时,用于加速前端页面开发的 Web框架(MVC) 是关键 分布式服务

分布式RPC框架性能大比拼 dubbo、motan、rpcx、gRPC、thrift的性能比较

Dubbo 是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成.不过,略有遗憾的是,据说在淘宝内部,dubbo由于跟淘宝另一个类似的框架HSF(非开源)有竞争关系,导致dubbo团队已经解散(参见http://www.oschina.net/news/55059/druid-1-0-9 中的评论),反到是当当网的扩展版本仍在持续发展,墙内开花墙外香.其它的一些知名电商如当当.京东.国美维护了自己的分支或

RPC框架Dubbo深入分析

1,背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进 单一应用架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本 此时,用于简化增删改查工作量的?数据访问框架(ORM)?是关键 垂直应用架构?当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率此时,用于加速前端页面开发的?Web框架(MVC)?是关键分布式服务架构