首页 > 其他分享 >Dubbo-RPC核心接口介绍

Dubbo-RPC核心接口介绍

时间:2023-02-06 06:55:06浏览次数:48  
标签:Dubbo String void Object 接口 RPC api Invoker key

前言

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具体支持的协议。 image.png

dubbo-rpc-api

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

核心接口

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

  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

image.png 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,String,void,Object,接口,RPC,api,Invoker,key
From: https://www.cnblogs.com/wtzbk/p/16950822.html

相关文章

  • 接口性能优化
    耗时统计在做接口的性能优化时,最重要的是知道时间消耗在哪里。可以用StopWatch,进行耗时统计。详情见:https://www.cnblogs.com/expiator/p/17045089.html多线程处理Co......
  • Dubbo2.7的Dubbo SPI实现原理细节
    总结/朱季谦本文主要记录我对DubboSPI实现原理的理解,至于什么是SPI,我这里就不像其他博文一样详细地从概念再到JavaSPI细细分析了,直接开门见山来分享我对DubboSPI的见解......
  • drf之异常处理,自动生成接口文档
    #7.异常处理ExceptionsRESTframework本身在APIView提供了异常处理,但是仅针对drf内部现有的接口开发相关的异常进行格式处理,但是开发中我们还会使用到各种的数据或者进......
  • 用了这18种方案,接口性能提高了100倍!
    前言大家好,我是捡田螺的小男孩。之前工作中,遇到一个504超时问题。原因是因为接口耗时过长,超过nginx配置的10秒。然后真枪实弹搞了一次接口性能优化,最后接口从11.3s降为1......
  • PHP对接抖音开发平台接口的详细教程
    目录一、说明二、代码三、代码运行需知四、功能扩展五、接口调用需要注意的点六、接口文档中的‘坑'(以订单列表接口为例)1、请求参数、响应参数代表的具体值不清......
  • USB接口型号和速度
    图片来源于下方B站视频......
  • 基于GenericAPIView+5个视图扩展类接口
    APIView与原生区别APIView属于drf视图基类#drf中APIView与django原生的View区别1.继承这个类后,视图方法中的request变为了drf的request而不是原生django的request2.......
  • python接口自动化-logging日志
    logging模块的日志级别:日志级别一共有5个从低到高如下,作用是在当你给python函数赋予日志器时,需要自己标记日志级别(后面会用到)DEBUG(调试级别):严重程度最低级别,详细程度最......
  • 基于.NetCore开发博客项目 StarBlog - (26) 集成Swagger接口文档
    前言这是StarBlog系列在2023年的第一篇更新......
  • brpc内存管理
    内存管理总是程序中的重要一环,在多线程时代,一个好的内存分配大都在如下两点间权衡:线程间竞争少。内存分配的粒度大都比较小,对性能敏感,如果不同的线程在大多数分配时会竞......