博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dubbo源码解析(三十一)远程调用——rmi协议
阅读量:6159 次
发布时间:2019-06-21

本文共 4315 字,大约阅读时间需要 14 分钟。

远程调用——rmi协议

目标:介绍rmi协议的设计和实现,介绍dubbo-rpc-rmi的源码。

前言

dubbo支持rmi协议,主要基于spring封装的org.springframework.remoting.rmi包来实现,当然最原始还是依赖 JDK 标准的java.rmi.*包,采用阻塞式短连接和 JDK 标准序列化方式。关于rmi协议的介绍可以参考dubbo官方文档。

地址:

源码分析

(一)RmiRemoteInvocation

该类继承了RemoteInvocation,主要是在RemoteInvocation的基础上新增dubbo自身所需的附加值,避免这些附加值没有被传递,为了做一些验证处理。

public class RmiRemoteInvocation extends RemoteInvocation {    private static final long serialVersionUID = 1L;    private static final String dubboAttachmentsAttrName = "dubbo.attachments";    /**     * executed on consumer side     */    public RmiRemoteInvocation(MethodInvocation methodInvocation) {        super(methodInvocation);        // 添加dubbo附加值的属性        addAttribute(dubboAttachmentsAttrName, new HashMap
(RpcContext.getContext().getAttachments())); } /** * Need to restore context on provider side (Though context will be overridden by Invocation's attachment * when ContextFilter gets executed, we will restore the attachment when Invocation is constructed, check more * 需要在提供者端恢复上下文(尽管上下文将被Invocation的附件覆盖 * 当ContextFilter执行时,我们将在构造Invocation时恢复附件,检查更多 * from {@link com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler} */ @SuppressWarnings("unchecked") @Override public Object invoke(Object targetObject) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { // 获得上下文 RpcContext context = RpcContext.getContext(); // 设置参数 context.setAttachments((Map
) getAttribute(dubboAttachmentsAttrName)); try { return super.invoke(targetObject); } finally { // 清空参数 context.setAttachments(null); } }}

(二)RmiProtocol

该类继承了AbstractProxyProtocol类,是rmi协议实现的核心,跟其他协议一样,也实现了自己的服务暴露和服务引用方法。

1.doExport

@Overrideprotected 
Runnable doExport(final T impl, Class
type, URL url) throws RpcException { // rmi暴露者 final RmiServiceExporter rmiServiceExporter = new RmiServiceExporter(); // 设置端口 rmiServiceExporter.setRegistryPort(url.getPort()); // 设置服务名称 rmiServiceExporter.setServiceName(url.getPath()); // 设置接口 rmiServiceExporter.setServiceInterface(type); // 设置服务实现 rmiServiceExporter.setService(impl); try { // 初始化bean的时候执行 rmiServiceExporter.afterPropertiesSet(); } catch (RemoteException e) { throw new RpcException(e.getMessage(), e); } return new Runnable() { @Override public void run() { try { // 销毁 rmiServiceExporter.destroy(); } catch (Throwable e) { logger.warn(e.getMessage(), e); } } };}

该方法是服务暴露的逻辑实现。

2.doRefer

@Override@SuppressWarnings("unchecked")protected 
T doRefer(final Class
serviceType, final URL url) throws RpcException { // FactoryBean对于RMI代理,支持传统的RMI服务和RMI调用者,创建RmiProxyFactoryBean对象 final RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean(); // RMI needs extra parameter since it uses customized remote invocation object // 检测版本 if (url.getParameter(Constants.DUBBO_VERSION_KEY, Version.getProtocolVersion()).equals(Version.getProtocolVersion())) { // Check dubbo version on provider, this feature only support // 设置RemoteInvocationFactory以用于此访问器 rmiProxyFactoryBean.setRemoteInvocationFactory(new RemoteInvocationFactory() { @Override public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { // 自定义调用工厂可以向调用添加更多上下文信息 return new RmiRemoteInvocation(methodInvocation); } }); } // 设置此远程访问者的目标服务的URL。URL必须与特定远程处理提供程序的规则兼容。 rmiProxyFactoryBean.setServiceUrl(url.toIdentityString()); // 设置要访问的服务的接口。界面必须适合特定的服务和远程处理策略 rmiProxyFactoryBean.setServiceInterface(serviceType); // 设置是否在找到RMI存根后缓存它 rmiProxyFactoryBean.setCacheStub(true); // 设置是否在启动时查找RMI存根 rmiProxyFactoryBean.setLookupStubOnStartup(true); // 设置是否在连接失败时刷新RMI存根 rmiProxyFactoryBean.setRefreshStubOnConnectFailure(true); // // 初始化bean的时候执行 rmiProxyFactoryBean.afterPropertiesSet(); return (T) rmiProxyFactoryBean.getObject();}

该方法是服务引用的逻辑实现。

后记

该部分相关的源码解析地址:

该文章讲解了远程调用中关于rmi协议实现的部分,逻辑比较简单。接下来我将开始对rpc模块关于thrift协议部分进行讲解。

转载地址:http://nnsfa.baihongyu.com/

你可能感兴趣的文章
关于静态属性和静态函数
查看>>
进程的基本属性:进程ID、父进程ID、进程组ID、会话和控制终端
查看>>
spring+jotm+ibatis+mysql实现JTA分布式事务
查看>>
MyBatis启动:MapperStatement创建
查看>>
调查问卷相关
查看>>
eclipse启动无响应,老是加载不了revert resources,或停留在Loading workbench状态
查看>>
1. Git-2.12.0-64-bit .exe下载
查看>>
怎样关闭“粘滞键”?
查看>>
[转]React 教程
查看>>
拓扑排序介绍
查看>>
eclipse打开工作空间(workspace)没有任务反应
查看>>
使用Sybmol模块来构建神经网络
查看>>
字符串去分割符号
查看>>
WPF中,多key值绑定问题,一个key绑定一个界面上的对象
查看>>
UML类图简明教程
查看>>
java反编译工具(Java Decompiler)
查看>>
Android开发之自定义对话框
查看>>
微信Access Token 缓存方法
查看>>
Eclipsed的SVN插件不能识别之前工作空间的项目
查看>>
Linux 查看iptables状态-重启
查看>>