Dubbo 协议
特性描述
Dubbo 默认协议使用单一长连接和 NIO 异步通信,适用于小数据量、高并发服务调用,以及服务消费者机器数量远大于服务提供者机器数量的情况。
反之,Dubbo 默认协议不适用于传输大数据量的服务,例如文件传输、视频传输等,除非请求量非常低。
- 传输器:mina、netty、grizzy
- 序列化:dubbo、hessian2、java、json
- 调度器:all、direct、message、execution、connection
- 线程池:fixed、cached
默认协议,使用基于 netty 3.2.5.Final
和 hessian2 3.2.1-fixed-2(阿里巴巴嵌入式版本)
的 tbremoting 交互。
- 连接数:单连接
- 连接方式:长连接
- 传输协议:TCP
- 传输方式:NIO 异步传输
- 序列化:Hessian 二进制序列化
- 适用范围:传入和传出参数数据包较小(建议小于 100K),消费者数量多于提供者,单个消费者无法填满提供者。尽量不要使用 dubbo 协议传输大文件或超大字符串。
- 适用场景:常规远程服务方法调用
约束
- 参数和返回值需要实现
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 不使用多出的枚举值进行传输 |
A->B | A 和 B 的属性同名但类型不同 | 抛出异常 |
A->B | serialId 不同 | 正常传输 |
接口中新增的方法对客户端没有影响,如果客户端不需要该方法,则客户端无需重新部署。输入参数和结果集中新增的属性对客户端没有影响,如果客户端不需要新的属性,则无需重新部署。
输入参数和结果集属性名称的更改对客户端序列化没有影响,但如果客户端没有重新部署,则无论输入还是输出,都无法获取属性名称已更改的属性值。
总结
- 服务端和客户端不需要完全一致的领域对象,但要遵循最大匹配原则。
- 会抛出异常的情况:枚举值类型多一个少一个,刚好用的是不同的那个,或者属性名相同,但类型不同。
适用场景
适用于并发量大、数据量小的服务调用,且服务消费者远大于服务提供者。
使用方法
配置协议
<dubbo:protocol name="dubbo" port="20880" />
设置默认协议
<dubbo:provider protocol="dubbo" />
设置服务的协议
<dubbo:service interface="..." protocol="dubbo" />
多端口
<dubbo:protocol id="dubbo1" name="dubbo" port="20880" />
<dubbo:protocol id="dubbo2" name="dubbo" port="20881" />
配置协议选项
<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" />
多连接配置
默认情况下,Dubbo 协议每个服务、每个提供者和每个消费者使用一个长连接。如果数据量较大,可以使用多个连接。
<dubbo:service interface="..." connections="1"/>
<dubbo:reference interface="..." connections="1"/>
<dubbo:service connections="0">
或<dubbo:reference connections="0">
表示服务使用 JVM 共享持久连接。**默认**<dubbo:service connections="1">
或<dubbo:reference connections="1">
表示服务使用独立持久连接。<dubbo:service connections="2">
或<dubbo:reference connections="2">
表示服务使用两个独立持久连接。
为了防止被大量连接挂起,可以在服务提供者上限制最大接收连接数,以实现服务提供者的自我保护。
<dubbo:protocol name="dubbo" accepts="1000" />
常见问题
问题 1
为什么消费者要比提供者多?
因为 dubbo 协议使用单一长连接,假设网络是千兆网卡 1024Mbit=128MByte,根据测试经验数据,每个连接最多只能跑到 7MByte(不同环境可能不同,仅供参考),理论上 1 个服务提供者需要 20 个服务消费者才能把网卡跑满。
问题 2
为什么不能传大包?
由于 dubbo 协议使用单一长连接,如果每次请求的数据包大小为 500KByte,假设网络是千兆网卡1024Mbit=128MByte,每个连接最多可以达到 7MByte(不同环境可能不同),单个服务提供者能提供的最大 TPS(每秒事务数)为:128MByte / 500KByte = 262。单个消费者调用单个服务提供者的最大 TPS(每秒事务数)为:7MByte / 500KByte = 14。如果可以接受,您可以考虑使用它,否则网络将成为瓶颈。
问题 3
为什么要使用异步单一长连接?
因为服务的现状是服务提供者很少,通常只有几台机器,但服务消费者很多,整个网站都可能在访问该服务。例如,Morgan 的提供者只有 6 个,但有数百个消费者。或者,每天有 1.5 亿次调用。如果使用传统的 Hessian 服务,服务提供者很容易不堪重负。通过单一连接,可以保证单个消费者不会压垮提供者,长期连接,减少连接握手验证等。并使用异步 IO,复用线程池,防止 C10K 问题。