Dubbo

1 注册与发现的流程图

在这里插入图片描述

2 Dubbo的核心配置

配置配置说明
dubbo:service服务配置
dubbo:reference引用配置
dubbo:protocol协议配置
dubbo:application应用配置
dubbo:module模块配置
dubbo:registry注册中心配置
dubbo:monitor监控中心配置
dubbo:provider提供方配置
dubbo:consumer消费方配置
dubbo:method方法配置
dubbo:argument参数配置

2.1 Dubbo 协议

Dubbo协议设计参考了现有TCP/IP协议。一次RPC调用包括协议头和协议体两个部分。16字节长的报文头部主要携带了魔法数(0xdabb),以及当前请求报文是否是Request、Response、心跳和事件的信息,请求时也会携带当前报文体内序列化协议编号。除此之外还携带了请求状态,以及请求唯一标识和报文体长度。
在这里插入图片描述
Dubbo协议字段解析:

偏移比特位字段描述作用
0~7魔数高位存储的是魔法数高位(0xda00)
8~15魔数低位存储的是魔法数低位(0xbb)
16数据包类型是否为双向RPC调用(比如方法调用有返回值),0为Response,1为Request
17调用方式仅在第16位被这设为1的情况下有效
0为单向调用,1位双向调用
比如在优雅停机时服务端发送readoly不需要双向调用,这里标志位就不会设定
18事件标识0为当前数据包是请求或响应包
1为当前数据包是心跳包,比如框架为了保活TCP连接,每次客户端和服务端相互发送心跳包时这个标志位被设定
设置了心跳报文不会透传到业务方法调用,仅用于框架内部保活机制
19~23序列化器编号2为HessianSerializatiion
3为JavaSerialization
4为CompactedJavaSerialization
6为FastJsonSerialization
7为NativJavaSerialization
8为KryoSerialization
9为FstSerialization
24~31状态20为OK
30为CLIENT_TIMEOUT
31为SERVER_TIMEOUT
40为BAD_REQUEST
50为BAD_RESPONSE
32~95请求编号这8个字节存储RPC请求的唯一id,用来将请求和响应做关联
96~127消息体长度占用的4个字节存储消息体长度。在一次RPC请求过程中,消息体中一次会存储7部分内容

在消息体中,客户端严格按照序列化顺序写入消息,服务端也会遵循相同的顺序读取消息,客户端发起请求的消息体一次保存下列内容:Dubbo版本号、服务接口名、服务接口版本、方法名、参数类型、方法参数值和请求额外参数(attachment)。

Dubbo其实就是用特殊符号0xdabb魔数来分隔处理粘包问题的。

2.2 Dubbo是如何做到正确响应调用线程

在这里插入图片描述

  1. 当客户端多个线程并发请求时,框架内部会调用Defaultfutre对象的get方法进行等待。
  2. 在请求发起时,框架内部会创建Request对象,这个时候会被分配一个唯一的id,DefaultFuture可以从Request对象中获取id,并将关联关系存储到静态HashMap中,就是上图中的Future集合。
  3. 当客户端收到响应时,会根据Response对象中的id,从Futures集合中查找对应的DefaultFuture对象,最终会唤醒对应的线程并通知结果。
  4. 客户端也会启动一个定时扫描线程去探测超时没有返回的请求。

Dubbo是一款开源RPC框架,底层使用Netty作为默认的数据传输方式,那么请求处理理论上是异步的,但是我们在使用Dubbo时,是同步拿到结果的,这是因为Dubbo框架帮我们做了异步转同步的操作。

3 在 Provider 上可以配置的 Consumer 端的属性有哪些?

1)timeout:方法调用超时。
2)retries:失败重试次数,默认重试 2 次。
3)loadbalance:负载均衡算法,默认随机。
4)actives:消费者端,最大并发调用限制。

4 Dubbo有哪几种集群容错方案,默认是哪种?

集群容错方案说明
Failover Cluster失败自动切换,自动重试其他服务器(默认)
Failfast Cluster快速失败,立即报错,只发起一次调用
Failsafe Cluster失败安全,出现异常时,直接忽略
Failback Cluster失败自动恢复,记录失败请求,定时重发
Forking Cluster并行调用多个服务器,只要一个成功即返回
Broadcast Cluster广播逐个调用所有提供者,任意一个报错则报错

5 Dubbo有哪几种负载均衡策略

负载均衡策略说明
Random LoadBalance随机,按权重设置随机概率(默认)
RoundRobin LoadBalance轮询,按公约后的权重设置轮询比率
LeastActive LoadBalance最少活跃调用数,相同活跃数的随机
ConsistentHash LoadBalaclava一致性Hash,相同参数的请求总是发到同一提供者

6 Dubbo工作原理

在这里插入图片描述

  • 服务提供者在启动的时候,会通过读取一些配置将服务实例化。
  • Proxy 封装服务调用接口,方便调用者调用。客户端获取 Proxy 时,可以像调用本地服务一样,调用远程服务。
  • Proxy 在封装时,需要调用 Protocol 定义协议格式,例如:Dubbo Protocol。
  • 将 Proxy 封装成 Invoker,它是真实服务调用的实例。
  • 将 Invoker 转化成Exporter,Exporter 只是把 Invoker 包装了一层,是为了在注册中心中暴露自己,方便消费者使用。
  • 将包装好的Exporter 注册到注册中心。
  • 服务消费者建立好实例,会到服务注册中心订阅服务提供者的元数据。元数据包括服务 IP 和端口以及调用方式(Proxy)。
  • 消费者会通过获取的 Proxy 进行调用。通过服务提供方包装过程可以知道,Proxy 实际包装了 Invoker 实体,因此需要使用 Invoker 进行调用。
  • 在 Invoker 调用之前,通过 Directory 获取服务提供者的Invoker 列表。在分布式的服务中有可能出现同一个服务,分布在不同的节点上。
  • 通过路由规则了解,服务需要从哪些节点获取。
  • Invoker 调用过程中,通过 Cluster 进行容错,如果遇到失败策略进行重试。
  • 调用中,由于多个服务可能会分布到不同的节点,就要通过 LoadBalance 来实现负载均衡。
  • Invoker 调用之前还需要经过Filter,它是一个过滤链,用来处理上下文,限流和计数的工作。
  • 生成过滤以后的 Invoker。
  • 用 Client 进行数据传输。
  • Codec 会根据 Protocol 定义的协议,进行协议的构造。
  • 构造完成的数据,通过序列化 Serialization 传输给服务提供者。
  • Request 已经到达了服务提供者,它会被分配到线程池(ThreadPool)中进行处理。
  • Server 拿到请求以后查找对应的 Exporter(包含有 Invoker)。
  • 由于 Exporter 也会被 Filter 层层包裹,通过Filter 后获得 Invoker最后,对服务提供者实体进行调用。

7 Dubbo 为什么比http快

  • 协议层区别
    HTTP ,HTTPS 使用的是 应用层协议 应用层协议:定义了用于在网络中进行通信和传输数据的接口。
    DUBBO接口使用的是 TCP/IP是传输层协议 传输层协议:管理着网络中的端到端的数据传输;

  • socket 层区别
    dubbo默认使用socket长连接,即首次访问建立连接以后,后续网络请求使用相同的网络通道。
    http1.1协议默认使用短连接,每次请求均需要进行三次握手,而http2.0协议开始将默认socket连接改为了长连接;

  • 数据传输
    dubbo 除了传输数据之外就没别的东西了。
    http 除了数据之外还有一堆的请求头(request)和响应头(response),这无疑会加重传输的负担;除此之外,如果是html的http请求,在发送请求和响应时会先将数据转成json在序列化,相比dubbo之下增加了一重转换。

8 Dubbo 3.0 新特性

8.1 注册模型的改变

在服务注册领域,市面上有两种模型,一种是应用级注册,一种是接口级注册,在Spring Cloud中, 一个应用是一个微服务,而在Dubbo2.7中,一个接口是一个微服务。 所以,Spring Cloud在进行服务注册时,是把应用名以及应用所在服务器的IP地址和应用所绑定的端 口注册到注册中心,相当于key是应用名,value是ip+port,而在Dubbo2.7中,是把接口名以及对应 应用的IP地址和所绑定的端口注册到注册中心,相当于key是接口名,value是ip+port。 所以在Dubbo2.7中,一个应用如果提供了10个Dubbo服务,那么注册中心中就会存储10对 keyvalue,而Spring Cloud就只会存一对keyvalue,所以以Spring Cloud为首的应用级注册是更加适 合的。 所以Dubbo3.0中将注册模型也改为了应用级注册,提升效率节省资源的同时,通过统一注册模型,也 为各个微服务框架的互通打下了基础。

8.2 新一代RPC协议-Triple协议

此时服务消费者最好能在发送的请求中,能标记所使用的序列化方式,这个标记是不能放在
Invocation对象中的,因为这个标记指的就是Invocation对象的序列化方法,服务端接收到字节流
后,首先得能拿到序列化标记,看采用的是什么序列化方法,再解析反序列化。
如果我们通过HTTP协议(特指HTTP1.x,HTTP2后面分析),那实现起来就比较方便,把序列化标记
放在请求头,Invocation对象序列化之后的结果放在请求体,服务端收到HTTP请求后,就先解析请求
头得到序列化标记,再取请求体进行反序列化。
但是Dubbo觉得用HTTP1.x协议性能太低了,原因在于:
所以有了dubbo协议,它就是为了解决上面两个问题,协议,描述的就是一份数据长什么样子,HTTP
协议也是一样,描述的就是一个HTTP请求长什么样子,以什么开始,到哪里结束。
比如HTTP协议就描述了,从第一个字节开始,遇到第一个空格符时,那就是表示前面每个字节对应的
字符组合成的字符串就表示请求方法(字符编码为ascii,一个字符对应一个字节),紧接着继续解析
字节,将会按HTTP协议格式解析出请求行、请求头,解析完请求头之后,取出content-length对应的
value,该value表示请求体的字节数,所以直接再获取content-length个字节,就表示获取到了请求
体(Invocation对象序列化之后的字节),从而一个HTTP请求就获取出来,下一个字节就是另外一个
HTTP请求了。

而dubbo协议也有自己的格式,比如:
在这里插入图片描述
dubbo协议在Dubbo框架内使用还是比较舒服的,并且dubbo协议相比于http1.x协议,性能会更好,因为请求中没有多余的无用的字节,都是必要的字节,并且每个Dubbo请求和响应中都有一个请求ID,这样可以基于一个Socket连接同时发送多个Dubbo请求,不用担心请求和响应对不上,所以dubbo协议成为了Dubbo框架中的默认协议。

但是dubbo协议一旦涉及到跨RPC框架,比如一个Dubbo服务要调用gPRC服务,就比较麻烦了,因为发一个dubbo协议的请求给一个gPRC服务,gPRC服务只会按照gRPC的格式来解析字节流,最终肯定会解析不成功的。

dubbo协议虽好,但是不够通用,所以这就出现了Triple协议,Triple协议是基于HTTP2,没有性能问题,另外HTTP协议非常通用,全世界都认它,兼容起来也比较简单,而且还有很多额外的功能,比如流式调用。

triple协议对比

  • triple协议基于的是HTTP2,rest协议目前基于的是HTTP1,都可以做到跨语言。
  • triple协议兼容了gPRC(Triple服务可以直接调用gRPC服务,反过来也可以),rest协议不行
  • triple协议支持流式调用,rest协议不行
  • rest协议更方便浏览器、客户端直接调用,triple协议不行(原理上支持,当得对triple协议的底层实现比较熟悉才行,得知道具体的请求头、请求体是怎么生成的)
  • dubbo协议是Dubbo3.0之前的默认协议,triple协议是Dubbo3.0之后的默认协议,优先用Triple协议
  • dubbo协议不是基于的HTTP,不够通用,triple协议底层基于HTTP所以更通用(比如跨语言、跨异构系统实现起来比较方便)
  • dubbo协议不支持流式调用

8.3 Dubbo3.0跨语言调用

在工作中,我们用Java语言通过Dubbo提供了一个服务,另外一个应用(也就是消费者)想要使用这个服务,如果消费者应用也是用Java语言开发的,那没什么好说的,直接在消费者应用引入Dubbo和服务接口相关的依赖即可。

但是,如果消费者应用不是用Java语言写的呢,比如是通过python或者go语言实现的,那就至少需要满足两个条件才能调用Java实现的Dubbo服务:
Dubbo一开始是用Java语言实现的,那现在就需要一个go语言实现的Dubbo框架,也就是现在的dubbo-go,然后在go项目中引入dubbo-go,从而可以在go项目中使用dubbo,比如使用go语言去暴露和使用Dubbo服务。
我们在使用Java语言开发一个Dubbo服务时,会把服务接口和相关类,单独抽象成为一个Maven项目,实际上就相当于一个单独的jar包,这个jar能被Java项目所使用,但不能被go项目所使用,所以go项目中该如何使用Java语言所定义的接口呢?直接用是不太可能的,只能通过间接的方式来解决这个问题,除开Java语言之外,那有没有其他技术也能定义接口呢?并且该技术也是Java和go都支持,这就是protobuf

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值