前言
Dubbo 支持的协议有很多,可以通过 dubbo:protocol
来配置不同的协议。包括以下几种:
- dubbo: 是Dubbo的默认协议。
- rmi: 采用 JDK 标准的
java.rmi.*
实现,采用阻塞式短连接和 JDK 标准序列化方式。 - hessian: 用于集成 Hessian 的服务,Hessian 底层采用 Http 通讯,采用 Servlet 暴露服务,Dubbo 缺省内嵌 Jetty 作为服务器实现
- http: 基于 HTTP 表单的远程调用协议,采用 Spring 的 HttpInvoker 实现
- webservice: 基于 WebService 的远程调用协议,基于 Apache CXF 的 frontend-simple 和 transports-http 实现
- thrift: 对原生的thrift协议做了扩展,在原生的 thrift 协议的基础上增加了一些额外的头信息。
- memcached: 基于memcached 实现 RPC 协议。
- redis: 基于 Redis 实现 RPC 协议。
- rest: 基于标准的Java REST API——JAX-RS 2.0(Java API for RESTful Web Services的简写)实现的REST调用支持。
dubbo 协议
这是Dubbo的默认缺省协议,采用单一长连接和NIO异步通信,适合于小数据量并发大的服务调用,以及服务消费者机器远大于服务提供者机器数的情况。
dubbo协议不适合传送大数据量的服务,比如传文件、传视频等。
其流程如图(来自官网):
其中, Transporter (传输层) 可以采用Mina 、 Netty 、grizzy, Serialization(序列化) 可以采用dubbo 、hessian2、 java、 json。
协议的配置方式
有三种方式:
配置协议
<dubbo:protocol name="dubbo" port="20880" />
其中相同的协议可以配置多端口:
<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" />
设置默认协议
`
xml
<dubbo:provider protocol=”dubbo” />
- 设置服务协议
``` xml
<dubbo:service protocol="dubbo" />
dubbo 协议在默认的情况下在每个服务的所有提供者和消费者之间使用单一长连接,如果传输数据量大,可以使用多个连接,如下配置:
<dubbo:service connections="1"/>
<dubbo:reference 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" />
多协议暴露服务
Dubbo 不仅提供了多种协议供使用,还支持让不同的服务使用不同的协议或让相同的服务使用不同的协议。
第一、不同的服务使用不同的协议,如小数量高并发的情况下则使用长连接协议会更快,大数据量使用短连接协议的效率更高。可参考下列的配置:
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:protocol name="rmi" port="1099"></dubbo:protocol>
<!-- 声明需要暴露的服务接口 -->
<!--使用 dubbo 协议暴露服务-->
<dubbo:service interface="com.joyxj.dubbo.demo.api.DemoService" ref="demoServiceImpl" protocol="dubbo" version="1.0.0"/>
<!--使用 rmi 协议暴露服务-->
<dubbo:service interface="com.joyxj.dubbo.demo.api.UserService" ref="userServiceImpl" protocol="rmi" version="1.0.0"/>
第二、同一个服务可能使用不同的协议。比如有的服役不仅仅是在服务之间调用,有时可能需要与HTTP客户端相互操作,这时就可以指定多个协议。类似如下的配置:
<dubbo:service interface="com.joyxj.dubbo.demo.api.DemoService" ref="demoServiceImpl" protocol="dubbo,hessian" version="1.0.0"/>
常见问题
消费者数量要比生产者数据更多。
因 dubbo 协议采用单一长连接,假设网络为千兆网卡,根据测试经验数据每条连接最多只能压满 7MByte(不同的环境可能不一样,供参考),理论上 1 个服务提供者需要 20 个服务消费者才能压满网卡。
建议传小包。
因 dubbo 协议采用单一长连接,如果每次请求的数据包大小为 500KByte,假设网络为千兆网卡 ,每条连接最大 7MByte(不同的环境可能不一样,供参考),单个服务提供者的 TPS(每秒处理事务数)最大为:128MByte / 500KByte = 262。单个消费者调用单个服务提供者的 TPS(每秒处理事务数)最大为:7MByte / 500KByte = 14。如果能接受,可以考虑使用,否则网络将成为瓶颈。
推荐使用异步单一长连接的方式。
因为服务的现状大都是服务提供者少,通常只有几台机器,而服务的消费者多,可能整个网站都在访问该服务,比如 Morgan 的提供者只有 6 台提供者,却有上百台消费者,每天有 1.5 亿次调用,如果采用常规的 hessian 服务,服务提供者很容易就被压跨,通过单一连接,保证单一消费者不会压死提供者,长连接,减少连接握手验证等,并使用异步 IO,复用线程池,防止 C10K 问题。