RMI 协议

特性描述

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

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

约束

  • 参数和返回值需要实现 Serializable 接口
  • dubbo 配置中的超时对 RMI 无效,需要使用 java 启动参数设置:-Dsun.rmi.transport.tcp.responseTimeout=3000,参见下面的 RMI 配置

使用场景

它是一组支持分布式应用开发的 Java API,实现不同操作系统之间程序的方法调用。

如何使用

导入依赖

从 Dubbo 3 开始,RMI 协议不再嵌入 Dubbo 中,需要单独引入独立的 模块

<dependency>
    <groupId>org.apache.dubbo.extensions</groupId>
    <artifactId>dubbo-rpc-rmi</artifactId>
    <version>1.0.0</version>
</dependency>
java -Dsun.rmi.transport.tcp.responseTimeout=3000

更多 RMI 优化参数,请参见 JDK 文档

接口描述

如果服务接口继承了 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 interface="..." protocol="rmi" />

多个端口

<dubbo:protocol id="rmi1" name="rmi" port="1099" />
<dubbo:protocol id="rmi2" name="rmi" port="2099" />

<dubbo:service interface="..." protocol="rmi1" />

Spring 兼容性

<dubbo:protocol name="rmi" codec="spring" />
  • 如果使用 RMI 为外部提供服务,在公司内网环境下应该不存在攻击风险。
  • 同时,如果应用依赖于旧的 common-collections 包,dubbo 将不会依赖于此包。请检查您的应用是否使用了它。
  • ** 存在反序列化安全风险。 ** 请检查应用:请将 commons-collections3 升级到 3.2.2;请将 commons-collections4 升级到 4.1。新版本的 commons-collections 解决了这个问题。

上次修改时间:2023 年 2 月 22 日: 合并重构网站 (#2293) (4517e8c1c9c)