前言

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. 系统整理K8S的配置管理实战-建议收藏系列

    目录 一.ConfigMap 1.1.创建 1.1.1.from-file 1.1.2.from-env-file 1.1.3.from-literal 1.1.4.基于yaml文件创建 1.2.Po ...

  2. java反序列化漏洞cc_link_one

    CC-LINK-one 前言 这里也正式进入的java的反序列化漏洞了,简单介绍一下CC是什么借用一些官方的解释:Apache Commons是Apache软件基金会的项目,曾经隶属于Jakarta项 ...

  3. Optional对象

    Optional对象 Optional 类是一个可以为null的容器对象,用于简化Java中对空值的判断处理,以防止出现各种空指针异常. 静态方法-of 必须确定对象不为null 在使用of封装成op ...

  4. 带你从入门到精通学习WireShark

    个人名片: 因为云计算成为了监控工程师‍ 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying 带你从入门到精通学习WireShark 一.什么是WireShark? 二.WireShar ...

  5. hashlib加密 logging日志 subprocess

    Day23 hashlib加密 logging日志 hahlib加密模块 logging日志模块 subprocess模块 1.hahlib加密模块 1.什么是加密? 将明文数据处理成密文数据的过程 ...

  6. .net6+wpf制作指定局域网ip无法上网的arp欺诈工具

    摘一段来自网上的arp欺诈解释:ARP欺骗(ARP spoofing),又称ARP毒化(ARP poisoning,网络上多译为ARP病毒)或ARP攻击,是针对以太网地址解析协议(ARP)的一种攻击技 ...

  7. bug处理记录:Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=512M; support was removed in 8.0

    1. 报错: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=512M; support was removed ...

  8. Kubernetes(k8s)存储管理之数据卷volumes(三):NFS数据卷

    目录 一.系统环境 二.前言 三.NFS数据卷 3.1 NFS数据卷概览 3.2 配置NFS服务端以及共享目录 3.3 配置NFS客户端 3.4 创建有NFS卷的pod 一.系统环境 服务器版本 do ...

  9. Javascript | 模拟mvc实现点餐程序

    MVC模式是一个比较成熟的开发模式.M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式.其中,View的定义比较清晰,就是用 ...

  10. go语言的grpc环境安装

    本文直接用安装包的方式安装. 源码编译安装参考:https://www.cnblogs.com/abc36725612/p/14288333.html 环境 golang的docker image d ...