dbuuo包括协议,分别为:
达博协议
RMI协议
粗麻布协议
HTTP协议
网络服务协议
thirift协议
memcached的的协议
Redis的的协议
达博协议
达博协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。
反之,达博协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。
达博协议特性
使用基于 mina 1.1.7
和 hessian 3.2.1
的 tbremoting 交互。
- 连接个数:单连接
- 连接方式:长连接
- 传输协议:TCP
- 传输方式:NIO 异步传输
- 序列化:Hessian 二进制序列化
- 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用 dubbo 协议传输大文件或超大字符串。
- 适用场景:常规远程服务方法调用
约束
- 参数及返回值需实现
Serializable
接口 - 参数及返回值不能自定义实现
List
,Map
,Number
,Date
,Calendar
等接口,只能用 JDK 自带的实现,因为 hessian 会做特殊处理,自定义实现类中的属性值都会丢失。 - Hessian 序列化,只传成员属性值和值的类型,不传方法或静态变量,兼容情况
配置
配置协议:
<dubbo:protocol name="dubbo" port="20880" />
设置默认协议:
<dubbo:provider protocol="dubbo" />
设置服务协议
<dubbo:service 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 connections="1"/>
<dubbo:reference connections="1"/>
rmi协议
rmi协议采用JDK标准的java.rmi.*实现,采用阻塞式短连接和JDK标准序列化方式。
注意:如果正在使用RMI提供服务给外部访问,同时应用里依赖了老的common-collections包的情况下,存在反序列化安全风险。
特性
- 连接个数:多连接
- 连接方式:短连接
- 传输协议:TCP
- 传输方式:同步传输
- 序列化:Java 标准二进制序列化
- 适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
- 适用场景:常规远程服务方法调用,与原生RMI服务互操作
约束
- 参数及返回值需实现
Serializable
接口 - dubbo 配置中的超时时间对 RMI 无效,需使用 java 启动参数设置:
-Dsun.rmi.transport.tcp.responseTimeout=3000
,参见下面的 RMI 配置
dubbo.properties配置
dubbo.service.protocol=rmi
RMI配置
java -Dsun.rmi.transport.tcp.responseTimeout=3000
接口
如果服务接口继承了 java.rmi.Remote
接口,可以和原生 RMI 互操作,即:
- 提供者用 Dubbo 的 RMI 协议暴露服务,消费者直接用标准 RMI 接口调用,
- 或者提供方用标准 RMI 暴露服务,消费方用 Dubbo 的 RMI 协议调用。
如果服务接口没有继承 java.rmi.Remote
接口:
- 缺省 Dubbo 将自动生成一个
com.xxx.XxxService$Remote
的接口,并继承java.rmi.Remote
接口,并以此接口暴露服务, - 但如果设置了
<dubbo:protocol name="rmi" codec="spring" />
,将不生成$Remote
接口,而使用 Spring 的RmiInvocationHandler
接口暴露服务,和 Spring 兼容。
配置
定义RMI协议:
<dubbo:protocol name="rmi" port="1099" />
设置默认协议
<dubbo:provider protocol="rmi" />
设置服务协议
<dubbo:service protocol="rmi" />
多端口
<dubbo:protocol id="rmi1" name="rmi" port="1099" />
<dubbo:protocol id="rmi2" name="rmi" port="2099" />
<dubbo:service protocol="rmi1" />
Spring兼容性
<dubbo:protocol name="rmi" codec="spring" />
hessian协议
Hessian 协议用于集成 Hessian 的服务,Hessian 底层采用 Http 通讯,采用 Servlet 暴露服务,Dubbo 默认内嵌 Jetty 作为服务器实现。
Dubbo 的 Hessian 协议可以和原生 Hessian 服务互操作,即:
- 提供者用 Dubbo 的 Hessian 协议暴露服务,消费者直接用标准 Hessian 接口调用
- 或者提供方用标准 Hessian 暴露服务,消费方用 Dubbo 的 Hessian 协议调用。
特性
- 连接个数:多连接
- 连接方式:短连接
- 传输协议:HTTP
- 传输方式:同步传输
- 序列化:Hessian二进制序列化
- 适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。
- 适用场景:页面传输,文件传输,或与原生hessian服务互操作
依赖
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.7</version>
</dependency>
约束
参数及返回值需实现 Serializable 接口
参数及返回值不能自定义实现 List, Map, Number, Date, Calendar 等接口,
只能用 JDK 自带的实现,因为 hessian 会做特殊处理,自定义实现类中的属性值都会丢失。
配置
定义hessian协议
<dubbo:protocol name="hessian" port="8080" server="jetty" />
设置默认协议
<dubbo:provider protocol="hessian" />
设置service协议:
<dubbo:service protocol="hessian" />
多端口
<dubbo:protocol id="hessian1" name="hessian" port="8080" />
<dubbo:protocol id="hessian2" name="hessian" port="8081" />
直连
<dubbo:reference id="helloService" interface="HelloWorld" url="hessian://10.20.153.10:8080/helloWorld" />
http协议
基于 HTTP 表单的远程调用协议,采用 Spring 的 HttpInvoker 实现
特性
- 连接个数:多连接
- 连接方式:短连接
- 传输协议:HTTP
- 传输方式:同步传输
- 序列化:表单序列化
- 适用范围:传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件。
- 适用场景:需同时给应用程序和浏览器 JS 使用的服务。
约束
参数及返回值需符合Bean规范
配置
配置协议:
<dubbo:protocol name="http" port="8080" />
配置jetty Server(默认)
<dubbo:protocol ... server="jetty" />
配置Servlet Bridge Service(推荐使用)
<dubbo:protocol ... server="servlet" />
配置DispatcherServlet
<servlet>
<servlet-name>dubbo</servlet-name>
<servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dubbo</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
注意,如果使用 servlet 派发请求:
- 协议的端口
<dubbo:protocol port="8080" />
必须与 servlet 容器的端口相同, - 协议的上下文路径
<dubbo:protocol contextpath="foo" />
必须与 servlet 应用的上下文路径相同。
webService协议
基于 WebService 的远程调用协议,基于 Apache CXF 的 frontend-simple
和 transports-http
实现 。
可以和原生 WebService 服务互操作,即:
- 提供者用 Dubbo 的 WebService 协议暴露服务,消费者直接用标准 WebService 接口调用,
- 或者提供方用标准 WebService 暴露服务,消费方用 Dubbo 的 WebService 协议调用
依赖
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-simple</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.6.1</version>
</dependency>
特性
- 连接个数:多连接
- 连接方式:短连接
- 传输协议:HTTP
- 传输方式:同步传输
- 序列化:SOAP 文本序列化
- 适用场景:系统集成,跨语言调用
约束
- 参数及返回值需实现
Serializable
接口 - 参数尽量使用基本类型和 POJO
配置
配置协议:
<dubbo:protocol name="webservice" port="8080" server="jetty" />
配置默认协议:
<dubbo:provider protocol="webservice" />
配置服务协议:
<dubbo:service protocol="webservice" />
多端口:
<dubbo:protocol id="webservice1" name="webservice" port="8080" />
<dubbo:protocol id="webservice2" name="webservice" port="8081" />
直连:
<dubbo:reference id="helloService" interface="HelloWorld"
url="webservice://10.20.153.10:8080/com.foo.HelloWorld" />
WSDL:
http://10.20.153.10:8080/com.foo.HelloWorld?wsdl
Jetty Server(默认):
<dubbo:protocol ... server="jetty" />
Servlet Bridge Server(推荐):
<dubbo:protocol ... server="servlet" />
配置DispatcherServlet
<servlet>
<servlet-name>dubbo</servlet-name>
<servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dubbo</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
注意,如果使用 servlet 派发请求:
- 协议的端口
<dubbo:protocol port="8080" />
必须与 servlet 容器的端口相同, - 协议的上下文路径
<dubbo:protocol contextpath="foo" />
必须与 servlet 应用的上下文路径相同。
thrift协议
当前dubbo支持的thrift协议是对thrift原生协议的扩展,在原生协议的基础上添加了一些额外的头信息,比如服务名称,魔术数字等。
使用dubbo thrift协议同样需要使用thrift的idl编译器编译生成相应的java代码
依赖
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.8.0</version>
</dependency>
配置
所有服务公用一个端口
<dubbo:protocol name="thrift" port="3030" />
常见问题
节俭不支持空值,即:不能再协议中传递空值
memcached的的协议
基于memcached的的实现RPC协议
注册的memcached的服务地址
RegistryFactory registryFactory =
ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("memcached://10.20.153.11/com.foo.BarService?
category=providers&dynamic=false&application=foo&group=member&loadbalance=consistenthash"));
在客户端引用
在客户端使用:
<dubbo:reference id="cache" interface="java.util.Map" group="member" />
或者点对点直连
<dubbo:reference id="cache" interface="java.util.Map" url="memcached://10.20.153.10:11211" />
也可以使用自定义的接口
<dubbo:reference id="cache" interface="com.foo.CacheService" url="memcached://10.20.153.10:11211" />
方法名建议和memcached的的标准方法名相同,即:GET(键),设置(键,值),删除(键)。
如果方法名和memcached的的标准方法名不相同,则需要配置映射关系
<dubbo:reference id="cache" interface="com.foo.CacheService"
url="memcached://10.20.153.10:11211" p:set="putFoo" p:get="getFoo" p:delete="removeFoo" />
Redis的的协议
基于Redis的的实现的RPC协议
注册的Redis的服务的地址
RegistryFactory registryFactory =
ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("redis://10.20.153.11/com.foo.BarService?
category=providers&dynamic=false&application=foo&group=member&loadbalance=consistenthash"));
在客户端引用
<dubbo:reference id="store" interface="java.util.Map" group="member" />
或者点对点直连
<dubbo:reference id="store" interface="java.util.Map" url="redis://10.20.153.10:6379" />
也可以使用自定义接口
<dubbo:reference id="store" interface="com.foo.StoreService" url="redis://10.20.153.10:6379" />
方法名建议和Redis的的标准方法名相同,即:获得(键),设置(键,值),DELET(键)。
如果方法名和redis的的标准方法名不相同,则需要配置映射关系
<dubbo:reference id="cache" interface="com.foo.CacheService"
url="redis://10.20.153.10:6379" p:set="putFoo" p:get="getFoo" p:delete="removeFoo" />