前言

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. Vue3 企业级优雅实战 - 组件库框架 - 3 搭建组件库开发环境

    前文已经初始化了 workspace-root,从本文开始就需要依次搭建组件库.example.文档.cli.本文内容是搭建 组件库的开发环境. 1 packages 目录 前面在项目根目录下创建了 ...

  2. 【lwip】12-一文解决TCP原理

    目录 前言 12.1 TCP协议简介 12.2 TCP相关的一些概念词 12.2.1 MSL 12.2.2 MSS 12.3 TCP工作特性 12.3.1 面向连接 12.3.2 全双工通信 12.3 ...

  3. 使用 Go HTTP 框架 Hertz 进行 JWT 认证

    前言 上一篇文章简单介绍了一个高性能的 Go HTTP 框架--Hertz,本篇文章将围绕 Hertz 开源仓库的一个 demo,讲述如何使用 Hertz 完成 JWT 的认证与授权流程. 这里要说明 ...

  4. Halo 主题 Redemption 首发版

    Redemption 一款专注阅读.写作的 Halo 博客主题.主要设计思想即是专注阅读.写作,是一款极简类型的博客主题. Redemption 部分设计灵感借鉴 Halo 博客 Zozo 主题,感谢 ...

  5. 实践案例:同程艺龙网的 Dubbo 升级经验总结

    本篇为同程艺龙旅行网 Apache Dubbo 的实践案例总结.感兴趣的朋友可以访问官网了解更多详情,或搜索关注官方微信公众号 Apache Dubbo 跟进最新动态. 作者信息: 严浩:同程艺龙高级 ...

  6. Qt_CLion

    目录 安装Qt和CLion 配置 CLion配置Qt的资源文件系统 在项目根文件夹下创建一个资源文件夹 在项目根目录下创建一个qrc文件 安装Qt和CLion 相关的安装网上有很多教程,安装步骤这里不 ...

  7. 【Java SE】Day07 API、Scanner类、Random类、ArrayList类

    一.API 1.概述: API(Application Programming Interface),应用程序编程接口 Java API:程序员的字典,是类的说明文档 2.使用步骤 帮助文档:JDK_ ...

  8. 【每日一题】【map操作】【滑动窗口所需元素】2021年12月22日-76. 最小覆盖子串

    给你一个字符串 s .一个字符串 t .返回 s 中涵盖 t 所有字符的最小子串.如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" . 注意: 对于 t 中重复字符 ...

  9. JS中BOM与DOM操作

    BOM操作 window对象 是与浏览器窗口做交互的语言 BOM = Browser Object Model 是指浏览器对象模型,它可以使Javascript 有能力和浏览器进行对话 window. ...

  10. 秒级查询之开源分布式SQL查询引擎Presto实操-上

    @ 目录 概述 定义 概念 架构 优缺点 连接器 部署 集群安装 常用配置说明 资源管理安装模式 安装命令行界面 基于Tableau Web 连接器 使用优化 数据存储 查询SQL优化 无缝替换Hiv ...