Dubbo远程传输协议详解

导读:本篇文章讲解 Dubbo远程传输协议详解,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

前言

上次小编为大家带来了Dubbo调用及容错机制详解,不知道大家有没有去看小编最后留下的问题,欢迎对文章进行评论也希望大家和小编多多交流。今天接着为大家带来Dubbo的内容,传输协议,上次调用机制中并没有涉及Dubbo传输的协议,这次容小编娓娓道来。

Dubbo核心协议

RPC协议概念

这边涉及到小编曾经被问到的问题,问dubbo采用什么协议,一般问这个问题的话,主要是针对应用协议而不是网络传输协议,所以TCP/UDP显然是不符合的,应用协议是在网络传输的基础至少构建出来的。大家要分清两种协议。以及知道面试官问的问题。
在⼀个典型RPC的使⽤场景中,包含了服务发现、负载、容错、网络传输、序列化等组件,其中RPC协议就指明了程序如何进行网络传输和序列化。也就是说⼀个RPC协议的实现就等于⼀个非透明的远程调用实现,那他是如何做到的的呢?如下图:
在这里插入图片描述
RPC协议组成:

1.地址:服务提供者地址和端口
2.报文编码:协议报⽂编码,分为请求头和请求体两部分。
3.序列化方式:将请求体序列化成对象

  • a.Hessian2Serialization
  • b.DubboSerialization
  • c.JavaSerializationd.JsonSerialization

4.运行服务:网络传输实现

  • a.netty
  • b.mina
  • c.RMI服务
  • d.servlet容器(jetty、Tomcat、Jboss)

dubbo支持协议

名称 实现描述 连接描述 适用场景
dubbo 传输服务:mina,netty(默认),grizzy;序列化:hessian2(默认),java,fastjson;报文:自定义报文 单个⻓连接NIO异步传输 1、常规RPC调用 2、传输数据量小 3、提供者少于消费者
rmi 传输:javarmi服务; 序列化:java原⽣⼆进制序列化 多个短连接.BIO同步传输 1、常规RPC调用 2、与原RMI客户端集成 3、可传少量⽂件 4、不防⽕墙穿透
hessian 传输服务:servlet容器; 序列化:hessian⼆进制序列化 基于Http协议传输,依赖servlet容器配置 1、提供者多于消费者 2、可传⼤字段和⽂件
http 传输服务:servlet容器; 序列化:java原⽣⼆进制序列化 依赖servlet容器配置 1、数据包⼤⼩混合
thrift 与thriftRPC实现集成,并在其基础上修改了报⽂头 ⻓连接、NIO异步传输

关于RMI不⽀持防⽕墙穿透的补充说明:
原因在于RMI底层实现中会有两个端口,⼀个是固定的用于服务发现的注册端口,另外会⽣成⼀个随机端⼝⽤于网络传输。因为这个随机端口就不能在防⽕墙中提前设置开放开。所以存在防⽕墙穿透问题。

dubbo协议(重点)

Dubbo协议是专门RPC远程调用所设计的协议,也是Dubbo默认协议,它是⼀种⼆进协议,特性是:体积小,编解码速度快。
协议报文
在这里插入图片描述

  • magic:类似java字节码文件里的魔数,用来判断是不是dubbo协议的数据包。魔数是常量0xdabb,⽤于判断报⽂的开始。
  • flag:标志位,⼀共8个地址位。低四位用来表示消息体数据⽤的序列化⼯具的类型(默认hessian),高四位中,第⼀位为1表示是request请求,第⼆位为1表示双向传输(即有返回response),第三位为1表示是心跳ping事件。
  • status:状态位,设置请求响应状态,dubbo定义了⼀些响应的类型。具体类型见com.alibaba.dubbo.remoting.exchange.Response
  • invokeid:消息id,long类型。每⼀个请求的唯⼀识别id(由于采⽤异步通讯的方式,⽤来把请求request和返回的response对应上)
  • bodylength:消息体Body长度,Int类型,即记录BodyContent有多少个字节。
    运行服务
    每个协议的使用都必须有⼀个运行服务器,用于进行IO数据传输,和编解码操作。比如Http协议的运⾏服务就是Tomcat\Jetty\Jboss\Apache\Nginx等。由于Http是知名的公共协议支持的服务器较多,如果是私有应用协议,或者Dubbo这类的特殊协议,就必须得自己使用Socket开发服务器,费时费力。还有另外⼀个选择就是选择netty、minia等网络框架进行开发,可节约⼤量开发成本。Dubbo同时⽀持Netty和minia,我们就用默认的Netty即可。
#服务选择netty,mina
dubbo.protocol.server=netty

线程池
Dubbo所依懒的Netty它是非阻塞式的IO通信,其网络传输所需线程并不多。但在业务处时,由于每个业务的响应时间不确定就需要⼀定数量的线程来支撑。以下是关于线程相关配置

#线程池类型fixed,cached,limited,eager
dubbo.protocol.threadpool=limited
#核心线程数,如果不够就加到队列 在CachedThreadPool,EagerThreadPool,LimitedThreadPool中使用
dubbo.protocol.corethreads=10
#核心线程满进入等待队列,如果满了创建新线程
dubbo.protocol.queues=10
#最大线程数量,默认200,超出后抛异常
dubbo.protocol.threads=100
dubbo.protocol.iothreads = 100
  • threadpool: 线程池类型,可选:fixed,cached,limited,eager, ⼀般配置cached
  • threads:服务最⼤线程池,根据上⾯的计算,来适当配置
  • iothreads:cpu个数+1 io线程池大小(固定大小),无需优化
  • accepts:服务提供方最大可接受连接数(长连接),默认0

相关源码
org.apache.dubbo.common.threadpool.support.fixed.FixedThreadPool//固定线程数量 (默认)org.apache.dubbo.common.threadpool.support.limited.LimitedThreadPool//增涨线程池org.apache.dubbo.common.threadpool.support.cached.CachedThreadPool//可回收线程,默认保持1分钟org.apache.dubbo.common.threadpool.support.eager.EagerThreadPool//自定义线程,先增涨后⼊队列,默认保持1分钟
大家可以看下源码。这边就不贴出代码了。这基本就是java并发的内容了,如果时间小编也会为大家带来并发编程的内容。

序列化
客户端与服务端在传递参数和结果时,都是JAVA对象,为了把这些对象能在⽹络上进⾏传输,必须把这些对象进行⼆进制序列化。好的序列化框架应⽀持以下特性:
1.体积小
2.序列化速度快
3.容错性强
第1、2点目的就是为了提⾼性能,而第3点目的是为版本升级时,最大化保证兼容(当然如果支持跨语言就更好了)。目前这几方面做得比较好的组件是Hessian2,这也是Dubbo协议默认序列化框架。
Hessian2序列化

  • 参数及返回值需实现 Serializable接口
  • 参数及返回值不能自定义实现 List,Map,Number,Date,Calendar等接口,只能用JDK自带的实现,因为 hessian会做特殊处理,自定义实现类中的属性值都会丢失。
  • Hessian序列化,只传成员属性值和值的类型,不传方法或静态变量,兼容情况
数据通讯 情况 结果
A ->B 类A多⼀种 属性(或者说类B少⼀种 属性) 不抛异常,A多的那 个属性的值,B没有, 其他正常
A ->B 枚举A多⼀种 枚举(或者说B少⼀种 枚举),A使⽤多 出来的枚举进⾏传输 抛异常
A ->B 枚举A多⼀种 枚举(或者说B少⼀种 枚举),A不使⽤ 多出来的枚举进⾏传输 不抛异常,B正常接 收数据
A ->B A和B的属性 名相同,但类型不相同 类型之间可以转换的不报错,如A类Long id,B类是String id,否则报异常
A ->B serialId不相同 正常传输

当接口增加方法,对客户端⽆影响,如果该方法不是客户端需要的,客户端不需要重新部署。输⼊参数和结果集中增加属性,对客户端⽆影响,如果客户端并不需要新属性,不用重新部署。输⼊参数和结果集属性名变化,对客户端序列化⽆影响,但是如果客户端不重新部署,不管输入还是输出,属性名变化的属性值是获取不到的。总结:服务器端和客户端对领域对象并不需要完全⼀致,而是按照最⼤匹配原则。

其他框架的序列化
此外Dubbo协议还⽀持以下序列化组件:

序列化框架 特点
fastjson ⽂本型:体积较⼤,性能慢、跨语⾔、可读性⾼
fst ⼆进制型:体积⼩、兼容JDK原⽣的序列化。要求JDK1.7⽀持。
java ⼆进制型:在JAVA原⽣的基础上可以写⼊Null
compactedjava ⼆进制型:与java类似,内容做了压缩
nativejava ⼆进制型:原⽣的JAVA序列化
kryo ⼆进制型:体积⽐hessian2还要⼩,但容错性没有hessian2好

在这里插入图片描述

序列化配置

#序列化框架
dubbo.protocol.serialization=fastjson  

RMI协议

RMI协议是原生的JAVA远程调⽤协议,其特性如下:

  • 运行服务:JAVA基于Socket自身实现
  • 连接方式:短连接,BIO同步传输
  • 序列化:JAVA原生,不支持其它序列化框架
  • 调⽤场景:与原RMI客户端集成
  • 其它特性:防火墙穿透问题
#mac查找当前进程所占端口
lsof-nP-p42161|grepLISTEN

Http协议

基于 HTTP表单的远程调⽤协议,采⽤ Spring的 HttpInvoker实现。其特性如下:

  • 连接个数:多连接
  • 连接方式:短连接
  • 传输协议:HTTP
  • 传输方式:同步传输
  • 序列化:表单序列化
  • 适⽤范围:传⼊传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传⼊参数,暂不支持传文件。
  • 适用场景:需同时给应用程序和浏览器 JS使用的服务

Hessian协议

Hessian协议用于集成 Hessian的服务,Hessian底层采用 Http通讯,采⽤Servlet暴露服务,Dubbo缺省内嵌 Jetty作为服务器实现。Dubbo的 Hessian协议可以和原生 Hessian服务互操作,即:提供者用 Dubbo的 Hessian协议暴露服务,消费者直接用标准 Hessian接口调用或者提供方用标准 Hessian暴露服务,消费方用 Dubbo的 Hessian协议调用。其特性如下:

  • 连接个数:多连接
  • 连接方式:短连接
  • 传输协议:HTTP
  • 传输方式:同步传输
  • 序列化:Hessian⼆进制序列化
  • 适用范围:传⼊传出参数数据包较⼤,提供者比消费者个数多,提供者压力较大,可传文件。
  • 适用场景:页面传输,文件传输,或与原生hessian服务互操作

总结

上面大家只要重点了解dubbo协议即可,如果想了解更多内容可以去dubbo官网>协议参考手册。在Dubbo中⼀个服务可以同时暴露给多个协议,这就是多协议使用,但一般情况下没有那么做的。好了今天就讲到这儿。谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/13574.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!