资讯专栏INFORMATION COLUMN

dubbo源码解析(三十一)远程调用——rmi协议

atinosun / 1969人阅读

摘要:关于协议的介绍可以参考官方文档。必须与特定远程处理提供程序的规则兼容。后记该部分相关的源码解析地址该文章讲解了远程调用中关于协议实现的部分,逻辑比较简单。

远程调用——rmi协议
目标:介绍rmi协议的设计和实现,介绍dubbo-rpc-rmi的源码。
前言

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

地址:http://dubbo.apache.org/zh-cn...
源码分析 (一)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
@Override
protected  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();
}

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

后记
该部分相关的源码解析地址:https://github.com/CrazyHZM/i...

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77386.html

相关文章

  • dubbo源码解析(四十八)异步化改造

    摘要:大揭秘异步化改造目标从源码的角度分析的新特性中对于异步化的改造原理。看源码解析四十六消费端发送请求过程讲到的十四的,在以前的逻辑会直接在方法中根据配置区分同步异步单向调用。改为关于可以参考源码解析十远程通信层的六。 2.7大揭秘——异步化改造 目标:从源码的角度分析2.7的新特性中对于异步化的改造原理。 前言 dubbo中提供了很多类型的协议,关于协议的系列可以查看下面的文章: du...

    lijinke666 评论0 收藏0
  • dubbo源码解析(四十六)消费端发送请求过程

    摘要:可以参考源码解析二十四远程调用协议的八。十六的该类也是用了适配器模式,该类主要的作用就是增加了心跳功能,可以参考源码解析十远程通信层的四。二十的可以参考源码解析十七远程通信的一。 2.7大揭秘——消费端发送请求过程 目标:从源码的角度分析一个服务方法调用经历怎么样的磨难以后到达服务端。 前言 前一篇文章讲到的是引用服务的过程,引用服务无非就是创建出一个代理。供消费者调用服务的相关方法。...

    fish 评论0 收藏0
  • dubbo源码解析(一)Hello,Dubbo

    摘要:英文全名为,也叫远程过程调用,其实就是一个计算机通信协议,它是一种通过网络从远程计算机程序上请求服务而不需要了解底层网络技术的协议。 Hello,Dubbo 你好,dubbo,初次见面,我想和你交个朋友。 Dubbo你到底是什么? 先给出一套官方的说法:Apache Dubbo是一款高性能、轻量级基于Java的RPC开源框架。 那么什么是RPC? 文档地址:http://dubbo.a...

    evin2016 评论0 收藏0
  • dubbo源码解析(二十一远程调用——Listener

    摘要:源码分析一该类实现了,是服务引用监听器的包装类。取消暴露遍历监听集合监听取消暴露该方法是对每个取消服务暴露的监听。五暴露服务取消暴露服务该类是服务暴露监听器的适配类,没有做实际的操作。 远程调用——Listener 目标:介绍dubbo-rpc-api中的各种listener监听器的实现逻辑,内容略少,随便撇两眼,不是重点。 前言 本文介绍监听器的相关逻辑。在服务引用和服务发现中监听器...

    simpleapples 评论0 收藏0
  • dubbo源码解析(四十七)服务端处理请求过程

    摘要:而存在的意义就是保证请求或响应对象可在线程池中被解码,解码完成后,就会分发到的。 2.7大揭秘——服务端处理请求过程 目标:从源码的角度分析服务端接收到请求后的一系列操作,最终把客户端需要的值返回。 前言 上一篇讲到了消费端发送请求的过程,该篇就要将服务端处理请求的过程。也就是当服务端收到请求数据包后的一系列处理以及如何返回最终结果。我们也知道消费端在发送请求的时候已经做了编码,所以我...

    yzzz 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<