前言

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主要用于销毁调用请求。

public interface Invoker<T> extends Node {

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

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

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

}
Invocation

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

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 调用方法结束时会触发这些回调。

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的实现。

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实现。

@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进行处理。

@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配置进行自定义。

@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. JavaScript之数组高阶API—reduce()

    一文搞懂JavaScript数组中最难的数组API--reduce() 前面我们讲了数组的一些基本方法,今天给大家讲一下数组的reduce(),它是数组里面非常重要也是比较难的函数,那么这篇文章就好好 ...

  2. java学习之JSP

    0x00前言 JSP:全拼写:java Server pages:java 服务器端页面 可以理解为一个特殊的页面:可以定义html代码也可以定义java的代码 定义:JSP是简化Servlet编写的 ...

  3. C#使用最小二乘法对多个离散点进行圆拟合

    /// <summary> /// 最小二乘法拟合圆,计算拟合圆半径和拟合圆圆心 /// </summary> /// <param name="points& ...

  4. Nginx如何配置隐藏index.php文件

    server { listen 80; #listen [::]:80 default_server ipv6only=on; server_name jiqing.dexin.com; index ...

  5. IPV4地址详解

    在互联网时代,相信会上网的人应该对IP地址都不是很陌生.就像我们每个人都有一个身份证号码一样,网络里的每个终端都使用一个IP地址用于标示自己.那么你知道哪些是保留地址?哪些是特殊地址吗? 一.保留地址 ...

  6. python进阶(28)import导入机制原理

    前言 在Python中,一个.py文件代表一个Module.在Module中可以是任何的符合Python文件格式的Python脚本.了解Module导入机制大有用处. 1. Module组成 一个.p ...

  7. 运用领域模型——DDD

    模型被用来描述人们所关注的现实或想法的某个方面.模型是一种简化.它是对现实的解释 -- 把与解决问题密切相关的方面抽象出来,而忽略无关的细节. 每个软件程序是为了执行用户的某项活动,或是满足客户的某种 ...

  8. 【重难点整理】通过kafka的全过程叙述kafka的原理、特性及常见问题

    一.kafka的实现原理 1.逻辑结构 2.组成 生产者:生产消息,来自服务.客户端.端口-- 消息本身:消息主体 topic主题:对消息的分类,例如数仓不同层中的不同类型数据(订单.用户--):自带 ...

  9. v-model双向绑定原理

    1 <div id="app"> 2 <div>{{msg}}</div> 3 <!-- 写法1 --> 4 <input t ...

  10. JAVA中生成随机数Random VS ThreadLocalRandom性能比较

    前言 大家项目中如果有生成随机数的需求,我想大多都会选择使用Random来实现,它内部使用了CAS来实现. 实际上,JDK1.7之后,提供了另外一个生成随机数的类ThreadLocalRandom,那 ...