前言

Dubbo源码阅读分享系列文章,欢迎大家关注点赞

SPI实现部分

  1. Dubbo-SPI机制
  2. Dubbo-Adaptive实现原理
  3. Dubbo-Activate实现原理
  4. Dubbo SPI-Wrapper

注册中心

  1. Dubbo-聊聊注册中心的设计
  2. Dubbo-时间轮设计

通信

  1. Dubbo-聊聊通信模块设计

RPC

  1. 聊聊Dubbo协议

整体介绍

Dubbo的RPC其实是对Protocol的封装,整体的结构与Remoting类似,dubbo-rpc-api是对具体协议、服务暴露、服务引用、代理等的抽象,是整个RPC中的核心,其他模块是对该层具体的实现,每个模块都是Dubbo具体支持的协议。

dubbo-rpc-api


dubbo-rpc-api整体模块如图所示,整体接口包括了filter、listener、protocol、proxy、support以及核心API,接下来我们先来看下核心的接口介绍。

核心接口

开始之前我们来先来回顾一下之前介绍RPC请求的过程,

  1. Rpc Client通过传入的IP、端口号、调用类以及方法的参数,通过动态代理找到具体的调用类的方法,将请求的类、方法序列化,传输到服务端;
  2. 当Rpc Service收到请求以后,将传入类和方法反序列化,通过反射找到对应的类的方法进行调用,最后将返回结果进行序列化,返回客户端;
  3. Rpc Client收到返回值以后,进行反序列化,最后将结果展示;

这里为什么要回顾整个过程,这样后面介绍抽象的接口的时候大家会更更容易理解为什么这么抽象。

Invoker

Invoker接口内部有三个方法,分别是getInterface、invoke、destroyAll,getInterface该方法主要是获取服务接口相关的信息,invoke主要是发起一次调用以及相应信息,destroyAll主要用于销毁调用请求。

  1. public interface Invoker<T> extends Node {

        //获取服务接口
        Class<T> getInterface();

        //发起调用
        Result invoke(Invocation invocation) throws RpcException;

        //销毁调用连接
        default void destroyAll() {
            destroy();
        }

    }
Invocation

Invocation是invoke的参数,内部抽象了RPC调用的目标服务、方法信息、相关参数信息、具体的参数值以及一些附加信息。

  1. public interface Invocation {

        //调用Service的唯一标识
        String getTargetServiceUniqueName();
        
        String getProtocolServiceKey();

        //调用的方法名称
        String getMethodName();

        //服务名称
        String getServiceName();

        //参数类型集合
        Class<?>[] getParameterTypes();

        //参数签名集合
        default String[] getCompatibleParamSignatures() {
            return Stream.of(getParameterTypes())
                    .map(Class::getName)
                    .toArray(String[]::new);
        }

        //调用具体的参数值
        Object[] getArguments();

        //调用关联的Invoker对象
        Map<String, String> getAttachments();

        @Experimental("Experiment api for supporting Object transmission")
        Map<String, Object> getObjectAttachments();

        void setAttachment(String key, String value);

        @Experimental("Experiment api for supporting Object transmission")
        void setAttachment(String key, Object value);

        @Experimental("Experiment api for supporting Object transmission")
        void setObjectAttachment(String key, Object value);

        void setAttachmentIfAbsent(String key, String value);

        @Experimental("Experiment api for supporting Object transmission")
        void setAttachmentIfAbsent(String key, Object value);

        @Experimental("Experiment api for supporting Object transmission")
        void setObjectAttachmentIfAbsent(String key, Object value);

        /**
         * get attachment by key.
         *
         * @return attachment value.
         * @serial
         */
        String getAttachment(String key);

        @Experimental("Experiment api for supporting Object transmission")
        Object getObjectAttachment(String key);

        /**
         * get attachment by key with default value.
         *
         * @return attachment value.
         * @serial
         */
        String getAttachment(String key, String defaultValue);

        @Experimental("Experiment api for supporting Object transmission")
        Object getObjectAttachment(String key, Object defaultValue);

        /**
         * get the invoker in current context.
         *
         * @return invoker.
         * @transient
         */
        Invoker<?> getInvoker();
        //Invoker对象可以设置一些KV属性,这些属性并不会传递给Provider
        Object put(Object key, Object value);

        Object get(Object key);

        Map<Object, Object> getAttributes();
    }
Result

Result接口是Invoker.invoke方法的返回值,该返回值包含了被调用方返回值(或是异常)以及附加信息,我们也可以添加回调方法,在 RPC 调用方法结束时会触发这些回调。

  1. public interface Result extends Serializable {

        //调用的返回值
        Object getValue();

        void setValue(Object value);

        //异常处理方法
        Throwable getException();

        void setException(Throwable t);

        boolean hasException();

        //复合操作,如果调用发生异常,则直接抛出异常,如果没有异常,则返回结果
        Object recreate() throws Throwable;

        //携带附加信息
        Map<String, String> getAttachments();

        @Experimental("Experiment api for supporting Object transmission")
        Map<String, Object> getObjectAttachments();

        void addAttachments(Map<String, String> map);

        @Experimental("Experiment api for supporting Object transmission")
        void addObjectAttachments(Map<String, Object> map);

        void setAttachments(Map<String, String> map);

        @Experimental("Experiment api for supporting Object transmission")
        void setObjectAttachments(Map<String, Object> map);

        String getAttachment(String key);

        @Experimental("Experiment api for supporting Object transmission")
        Object getObjectAttachment(String key);

        String getAttachment(String key, String defaultValue);

        @Experimental("Experiment api for supporting Object transmission")
        Object getObjectAttachment(String key, Object defaultValue);

        void setAttachment(String key, String value);

        @Experimental("Experiment api for supporting Object transmission")
        void setAttachment(String key, Object value);

        @Experimental("Experiment api for supporting Object transmission")
        void setObjectAttachment(String key, Object value);

        //添加回调 当RPC调用完成时,会触发回调
        Result whenCompleteWithContext(BiConsumer<Result, Throwable> fn);

        <U> CompletableFuture<U> thenApply(Function<Result, ? extends U> fn);

        //阻塞线程,等待此次RPC调用完成
        Result get() throws InterruptedException, ExecutionException;

        Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
    }
Exporter

Exporter暴露Invoker的实现,就是让Provider能够根据请求的各种信息,找到对应的Invoker的实现。

  1. public interface Exporter<T> {

        //获取Invoker对象
        Invoker<T> getInvoker();

        //取消Invoker对象
        void unexport();

    }
Protocol

Protocol接口主要有三个核心方法export、refer以及destroy,export主要是将Invoker服务暴露出去,refer引用一个服务将Invoker对象返回,destroy主要是销毁Invoker,释放Protocol对底层的占用。Protocol接口的实现中,export方法并不是简单地将Invoker对象包装成Exporter对象返回,其中还涉及代理对象的创建、底层Server的启动等操作;refer方法除了根据传入的type类型以及URL参数查询Invoker之外,还涉及相关Client的创建等操作。
此外该接口被SPI修饰,export和refer被Adaptive修饰,因此对于Protocol可以动态选择实现,此外Dubbo也提供多种Protocol实现。

  1. @SPI("dubbo")
    public interface Protocol {

        //默认端口
        int getDefaultPort();

        //将一个Invoker暴露,该方法必须是幂等的
        @Adaptive
        <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;

        //引用一个Invoker,返回一个Invoker对象
        @Adaptive
        <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;

        //销毁export方法以及refer方法使用到的Invoker对象,释放当前Protocol对象底层占用的资源
        void destroy();

        //返回当前Protocol底层的全部ProtocolServer
        default List<ProtocolServer> getServers() {
            return Collections.emptyList();
        }

    }
Filter

Filter接口用来拦截Dubbo请求,定义了一个invoke方法将请求传递给后续的Invoker进行处理。

  1. @SPI
    public interface Filter {

        //将请求传给后续的Invoker处理
        Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException;

        //监听响应以及异常
        interface Listener {

            void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation);

            void onError(Throwable t, Invoker<?> invoker, Invocation invocation);
        }

    }
ProxyFactory


ProxyFactory接口主要的功能是用来创建代理对象,此外ProxyFactory也是一个扩展接口,getProxy方法为Invoker创建代理对象,getInvoker方法将代理对象转为Invoker对象,默认采用javassist生成代理对象,Dubbo还提供很多种实现,可以通过SPI配置进行自定义。

  1. @SPI("javassist")
    public interface ProxyFactory {
        //将Invoker对象转为代理对象
        @Adaptive({PROXY_KEY})
        <T> T getProxy(Invoker<T> invoker) throws RpcException;
        @Adaptive({PROXY_KEY})
        <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException;
        //将proxy对象转为Invoker
        @Adaptive({PROXY_KEY})
        <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
    }

结束

欢迎大家点点关注,点点赞!

Dubbo-RPC核心接口介绍的更多相关文章

  1. dubbo 提示No such extension Filter for filter/com.alibaba.dubbo.rpc.Filter

    配置时 <dubbo:provider filter="DubboExceptionFilter"></dubbo:provider> DubboExcep ...

  2. 【DUBBO】dubbo的LoadBalance接口

    LoadBalance负载均衡, 负责从多个 Invokers中选出具体的一个Invoker用于本次调用,调用过程中包含了负载均衡的算法,调用失败后需要重新选择 --->类注解@SPI说明可以基 ...

  3. Spring Cloud 系列之 Dubbo RPC 通信

    Dubbo 介绍 官网:http://dubbo.apache.org/zh-cn/ Github:https://github.com/apache/dubbo 2018 年 2 月 15 日,阿里 ...

  4. 如何开发基于Dubbo RPC的分布式服务?

    什么是Dubbo? Dubbo能做什么? 在Crystal框架下,如何开发基于Dubbo RPC的服务? 在Crystal框架下,如何调用Dubbo RPC服务? 相关的文章 什么是Dubbo? Du ...

  5. dubbo实现原理简单介绍

    一.什么是dubbo   Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务模型的角度来看,     ...

  6. Dubbo RPC源码解读

    https://yq.aliyun.com/articles/272405#27 本文代码摘录的时候,将一些与本流程无关的内容去掉了,如有需要请看源码. 一.闲言碎语 使用rpc框架已经多年了,虽然之 ...

  7. 看了这篇Dubbo RPC面试题,让天下没有难面的面试题!

      前言: RPC非常重要,很多人面试的时候都挂在了这个地方!你要是还不懂RPC是什么?他的基本原理是什么?你一定要把下边的内容记起来!好好研究一下!特别是文中给出的一张关于RPC的基本流程图,重点中 ...

  8. 精选 Dubbo RPC 面试题,比较全面,含答案

    精选 Dubbo RPC 面试题,比较全面,含答案 hu1991die 搜云库技术团队 搜云库技术团队 微信号 souyunku 功能介绍 专注于分享最有价值的互联网技术干货文章,内容覆盖,Java后 ...

  9. dubbo 分布式服务框架 介绍

    Dubbo是阿里巴巴内部的SOA服务化治理方案的核心框架,每天为2000+ 个服务提供3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点.Dubbo自2011年开源后, ...

  10. 高性能消息队列 CKafka 核心原理介绍(上)

    欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:闫燕飞 1.背景 Ckafka是基础架构部开发的高性能.高可用消息中间件,其主要用于消息传输.网站活动追踪.运营监控.日志聚合.流式 ...

随机推荐

  1. JS逆向实战6-- x轴 y轴 过点触验证码

    点触验证码是一种常见的反爬手段 解决方案有两种:一种是直接解决,这需要深度学习机器学习等图像处理技术,以大量的数据训练识别模型,最终达到模型足矣识别图片中的文字提示和应该点击的区域之间的对应关系. 这 ...

  2. 树上启发式合并(dsu on tree)

    树上启发式合并属于暴力的优化,复杂度O(nlogn) 主要解决的问题特点在于: 1.对于树上的某些信息进行查询 2.一般问题的解决不包含对树的修改,所有答案可以离线解决 算法思路:这类问题的特点在于父 ...

  3. JavaScript常用工具函数

    检测数据是不是除了symbol外的原始数据 function isStatic(value) { return ( typeof value === 'string' || typeof value ...

  4. 【iOS逆向】某营业厅算法分析

    阅读此文档的过程中遇到任何问题,请关注公众号[移动端Android和iOS开发技术分享]或加QQ群[812546729] 1.目标 使用frida stalker分析某营业厅的签名算法. 2.操作环境 ...

  5. Armv8之Execution State 和 Exception Level(一)

    @ 目录 1. 典型的Exception Level使用模型 2.异常相关术语 3. Execution State 3.1 两种Execution State 3.2 决定Execution Sta ...

  6. netty系列之:在netty中使用proxy protocol

    目录 简介 netty对proxy protocol协议的支持 HAProxyMessage的编码解码器 netty中proxy protocol的代码示例 总结 简介 我们知道proxy proto ...

  7. Linux 交叉编译使用代码覆盖GCOV及LCOV

    1. GCOV GCOV是GCC自带的代码覆盖工具,GCOV. 在 GCC 编译的时加入特殊的编译选项,生成可执行文件,和 *.gcno: 运行(测试)生成的可执行文件,生成了 *.gcda 数据文件 ...

  8. 【每日一题】【二分mid&贪心】2022年2月8日-NC163 最长上升子序列(一)

    1.描述给定一个长度为 n 的数组 arr,求它的最长严格上升子序列的长度.所谓子序列,指一个数组删掉一些数(也可以不删)之后,形成的新数组.例如 [1,5,3,7,3] 数组,其子序列有:[1,3, ...

  9. 【企业流行新数仓】Day03:SuperSet图表,Ranger权限、脱敏、行级别过滤,Atlas元数据、查询和查看全表/字段血缘依赖,Zabbix告警

    一.SuperSet-图表展示 1.概念 (1)概念 通过dashboard(仪表盘)对图表中的数据进行展示 BI工具:根据配置的要求,进行数据源的配置即可 是准商业级别的BI web应用 (2)原理 ...

  10. 在OpenEuler22.09(也适用于CentOS7+)编译安装Python3.9,并于原Python共存-指南

    指南使用操作系统:OpenEuler 22.09(网络安装,最小安装,使用默认源) 指南使用系统自带Python版本:3.10(高版本,这不是3.1喔) 1. 安装基本的编译环境 yum -y ins ...