Java RMI远程调用,客户端会创建TCP连接来跟服务器端会话。客户端需要创建并管理这些连接。连接的复用可以减少频繁的创建TCP连接,要实现并发的远程访问又需要创建多个连接。那么Java RMI是怎么管理TCP连接的呢?本文简单探索了JDK19中RMI连接管理的模型。
核心实现类
JDK默认使用UnicastRef来发起远程调用,每个UnicastRef对象对应一个客户端的代理对象。每个UnicastRef对象对应1个TCPChannel对象,TCPChannel内的TCPEndpoint就包含请求的IP+port。TCPChannel内部维护一个可复用的连接列表freeList。TCPChannel创建连接默认使用了TCPDirectSocketFactory,而TCPDirectSocketFactory每次都会创建新的连接。
连接池模型
阅读代码后可见JDK里的连接管理的模型其实较为简单:
- 每个远程调用的对象都会维护自己的连接池,连接池里没有可用链接就创建新的连接。
- 新的连接使用完后放入连接池freeList。
- 每个连接默认如果空闲了15秒则被清理掉。
- 默认没有对最大可创建的连接数做限制,所以任何一次远程调用都不会因为连接不够用而被阻塞。
单次远程调用的过程如图:
并发问题
- 每个连接被获取后只会被当前的线程使用,所以没有并发使用同一个连接的问题。
- 可能同时有多个线程使用同一个对象发起远程调用,所以存在并发的从连接池(freeList)中获取连接的情况,因此JDK里对freeList的访问都加了synchronized锁。
可能的优化
以上可见RMI同样可以借鉴HTTP2的Multiplexing多路复用的思路进行优化。
















