Dubbo协议及序列化

Dubbo是 Alibaba 开源的分布式服务框架远程调用框架,在网络间传输数据,就需要通信协议和序列化。

一 通信协议

Dubbo支持dubbo、rmi、hessian、http、webservice、thrift、redis等多种协议,但是Dubbo官网是推荐我们使用Dubbo协议的,默认也是用的dubbo协议。

先介绍几种常见的协议:

1. dubbo协议
缺省协议,使用基于mina1.1.7+hessian3.2.1的tbremoting交互。
连接个数:单连接
连接方式:长连接
传输协议:TCP
传输方式:NIO异步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大文件或超大字符串。
适用场景:常规远程服务方法调用

1、dubbo默认采用dubbo协议,dubbo协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况
2、他不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。
配置如下:

<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name=“dubbo” port=“9090” server=“netty” client=“netty” codec=“dubbo”
serialization=“hessian2” charset=“UTF-8” threadpool=“fixed” threads=“100” queues=“0” iothreads=“9”
buffer=“8192” accepts=“1000” payload=“8388608” />
3、Dubbo协议缺省每服务每提供者每消费者使用单一长连接,如果数据量较大,可以使用多个连接。

<dubbo:protocol name="dubbo" connections="2" />
4、为防止被大量连接撑挂,可在服务提供方限制大接收连接数,以实现服务提供方自我保护

<dubbo:protocol name="dubbo" accepts="1000" />

2. rmi协议
Java标准的远程调用协议。
连接个数:多连接
连接方式:短连接
传输协议:TCP
传输方式:同步传输
序列化:Java标准二进制序列化
适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
适用场景:常规远程服务方法调用,与原生RMI服务互操作

RMI协议采用JDK标准的java.rmi.*实现,采用阻塞式短连接和JDK标准序列化方式 。

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

1、Hessian协议用于集成Hessian的服务,Hessian底层采用Http通讯,采用Servlet暴露服务,Dubbo缺省内嵌Jetty作为服务器实现。
2、Hessian是Caucho开源的一个RPC框架:http://hessian.caucho.com,其通讯效率高于WebService和Java自带的序列化。

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

5. webservice协议

基于WebService的远程调用协议。 
连接个数:多连接 
连接方式:短连接 
传输协议:HTTP 
传输方式:同步传输 
序列化:SOAP文本序列化 
适用场景:系统集成,跨语言调用

二 序列化

序列化是将一个对象变成一个二进制流就是序列化, 反序列化是将二进制流转换成对象。

为什么要序列化?

1. 减小内存空间和网络传输的带宽

2. 分布式的可扩展性

3. 通用性,接口可共用。

Dubbo序列化支持java、compactedjava、nativejava、fastjson、dubbo、fst、hessian2、kryo,其中默认hessian2。其中java、compactedjava、nativejava属于原生java的序列化。

dubbo序列化:阿里尚未开发成熟的高效java序列化实现,阿里不建议在生产环境使用它。

hessian2序列化:hessian是一种跨语言的高效二进制序列化方式。但这里实际不是原生的hessian2序列化,而是阿里修改过的,它是dubbo RPC默认启用的序列化方式。
json序列化:目前有两种实现,一种是采用的阿里的fastjson库,另一种是采用dubbo中自己实现的简单json库,但其实现都不是特别成熟,而且json这种文本序列化性能一般不如上面两种二进制序列化。
java序列化:主要是采用JDK自带的Java序列化实现,性能很不理想。

dubbo序列化主要由Serialization(序列化策略)、DataInput(反序列化,二进制->对象)、DataOutput(序列化,对象->二进制流) 来进行数据的序列化与反序列化。其关系类图为:

看一下Serialization的接口:

1 1 /** 2 2 * Serialization. (SPI, Singleton, ThreadSafe) 3 3 */ 4 4 @SPI("hessian2") 5 5 public interface Serialization { 6 6 7 7 /** 8 8 * get content type id 9 9 * 1010 * @return content type id 1111 */ 1212 byte getContentTypeId(); 1313 1414 /** 1515 * get content type 1616 * 1717 * @return content type 1818 */ 1919 String getContentType(); 2020 2121 /** 2222 * create serializer 2323 * 2424 * @param url 2525 * @param output 2626 * @return serializer 2727 * @throws IOException 2828 */ 2929 @Adaptive 3030 ObjectOutput serialize(URL url, OutputStream output) throws IOException; 3131 3232 /** 3333 * create deserializer 3434 * 3535 * @param url 3636 * @param input 3737 * @return deserializer 3838 * @throws IOException 3939 */ 4040 @Adaptive 4141 ObjectInput deserialize(URL url, InputStream input) throws IOException; 4242 4343 }

从上面类图可以看出各个Serialization实现类调用了各自的output和input,我们看一下默认的hessian2的实现。

1 1 public class Hessian2Serialization implements Serialization { 2 2 3 3 public static final byte ID = 2; 4 4 5 5 public byte getContentTypeId() { 6 6 return ID; 7 7 } 8 8 9 9 public String getContentType() { 1010 return "x-application/hessian2"; 1111 } 1212 1313 public ObjectOutput serialize(URL url, OutputStream out) throws IOException { 1414 return new Hessian2ObjectOutput(out); 1515 } 1616 1717 public ObjectInput deserialize(URL url, InputStream is) throws IOException { 1818 return new Hessian2ObjectInput(is); 1919 } 2020 2121 }

output实现类:

1 1 public class Hessian2ObjectOutput implements ObjectOutput { 2 2 private final Hessian2Output mH2o; 3 3 4 4 public Hessian2ObjectOutput(OutputStream os) { 5 5 mH2o = new Hessian2Output(os); 6 6 mH2o.setSerializerFactory(Hessian2SerializerFactory.SERIALIZER_FACTORY); 7 7 } 8 8 9 9 public void writeBool(boolean v) throws IOException { 1010 mH2o.writeBoolean(v); 1111 } 1212 1313 public void writeByte(byte v) throws IOException { 1414 mH2o.writeInt(v); 1515 } 1616 1717 public void writeShort(short v) throws IOException { 1818 mH2o.writeInt(v); 1919 } 2020 2121 public void writeInt(int v) throws IOException { 2222 mH2o.writeInt(v); 2323 } 2424 2525 public void writeLong(long v) throws IOException { 2626 mH2o.writeLong(v); 2727 } 2828 2929 public void writeFloat(float v) throws IOException { 3030 mH2o.writeDouble(v); 3131 } 3232 3333 public void writeDouble(double v) throws IOException { 3434 mH2o.writeDouble(v); 3535 } 3636 3737 public void writeBytes(byte[] b) throws IOException { 3838 mH2o.writeBytes(b); 3939 } 4040 4141 public void writeBytes(byte[] b, int off, int len) throws IOException { 4242 mH2o.writeBytes(b, off, len); 4343 } 4444 4545 public void writeUTF(String v) throws IOException { 4646 mH2o.writeString(v); 4747 } 4848 4949 public void writeObject(Object obj) throws IOException { 5050 mH2o.writeObject(obj); 5151 } 5252 5353 public void flushBuffer() throws IOException { 5454 mH2o.flushBuffer(); 5555 } 5656 }

input实现类:

1 1 public class Hessian2ObjectInput implements ObjectInput { 2 2 private final Hessian2Input mH2i; 3 3 4 4 public Hessian2ObjectInput(InputStream is) { 5 5 mH2i = new Hessian2Input(is); 6 6 mH2i.setSerializerFactory(Hessian2SerializerFactory.SERIALIZER_FACTORY); 7 7 } 8 8 9 9 public boolean readBool() throws IOException { 1010 return mH2i.readBoolean(); 1111 } 1212 1313 public byte readByte() throws IOException { 1414 return (byte) mH2i.readInt(); 1515 } 1616 1717 public short readShort() throws IOException { 1818 return (short) mH2i.readInt(); 1919 } 2020 2121 public int readInt() throws IOException { 2222 return mH2i.readInt(); 2323 } 2424 2525 public long readLong() throws IOException { 2626 return mH2i.readLong(); 2727 } 2828 2929 public float readFloat() throws IOException { 3030 return (float) mH2i.readDouble(); 3131 } 3232 3333 public double readDouble() throws IOException { 3434 return mH2i.readDouble(); 3535 } 3636 3737 public byte[] readBytes() throws IOException { 3838 return mH2i.readBytes(); 3939 } 4040 4141 public String readUTF() throws IOException { 4242 return mH2i.readString(); 4343 } 4444 4545 public Object readObject() throws IOException { 4646 return mH2i.readObject(); 4747 } 4848 4949 @SuppressWarnings("unchecked") 5050 public <T> T readObject(Class<T> cls) throws IOException, 5151 ClassNotFoundException { 5252 return (T) mH2i.readObject(cls); 5353 } 5454 5555 public <T> T readObject(Class<T> cls, Type type) throws IOException, ClassNotFoundException { 5656 return readObject(cls); 5757 } 5858 5959 }

其他的实现类也是类似。

如果想要改变序列化方式,可以更改配置,xml配置可以使用<dubbo:protocol serialization="fastjson" />,springboot配置可以使用dubbo.protocol.serialization=fastjson。

hessian 是一个比较老的序列化实现了,而且它是跨语言的,所以不是单独针对java进行优化的。而dubbo RPC实际上完全是一种Java to Java的远程调用,其实没有必要采用跨语言的序列化方式(当然肯定也不排斥跨语言的序列化)。

现在有一些新的序列化:

专门针对Java语言的:Kryo,FST等等
跨语言的:Protostuff,ProtoBuf,Thrift,Avro,MsgPack等等
这些序列化方式的性能多数都显著优于 hessian2 (甚至包括尚未成熟的dubbo序列化)。所以我们可以 
为 dubbo 引入 Kryo 和 FST 这两种高效 Java 来优化 dubbo 的序列化。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Dubbo 序列化协议 5 连问,你接得住不?

编辑|Java之间来源| www.toutiao.com/i6745361206137061895/1)dubbo支持哪些通信协议?2)支持哪些序列化协议?3)说一下Hessian的数据结构?4)PB知道吗?5)为什么PB的效率是最高的?面试官心理分析上一个问题,说说dubbo的基本工作原理,那是

Dubbo协议及序列化 - HelloWorld