• Dubbo漫谈之服务提供端


    上一篇的内容,继续Dubbo服务提供端模块的分解,先来回顾下RPC的图:
    0
    Consumer调用走到网络部分就结束了,下面来分解下图右半部分Dubbo的实现。

    Dubbo RPC 服务端组件

    还是按照图的顺序自左至右,一个请求跨越了网络,数据走到Provider这一侧。首先自然是反序列化和协议解析,这个跟Consumer端正好是反的,但是代码是一起的,分别是Serialization中的deserialize()方法和Codec2中的decode()方法。 

    请求传输

    Provider要提供服务,必须在某一端口上监听来接收数据,所以跟Client端对应要有个Server。

    Server

    为了支持多协议,Dubbo将Server抽象为ExchangeServer接口:
    public interface ExchangeServer extends RemotingServer {
        /**
         * 获取所有和client的Channel
         */
        Collection<ExchangeChannel> getExchangeChannels();
        /**
         * 获取指定Client的Channel
         */
        ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress);
    }
    public interface ExchangeChannel extends Channel {
        /**
         * 发送请求
         */
        CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException;
        /**
         * 接收数据的handler
         */
        ExchangeHandler getExchangeHandler();
        /**
         * 关闭Channel
         */
        @Override
        void close(int timeout);
    }
    跟上一篇的ExchangeClient一样,ExchangeServer自然也是从Exchanger接口里来的。
    @SPI(HeaderExchanger.NAME)
    public interface Exchanger {
        /**
         * 开启一个服务端Server
         */
        @Adaptive({Constants.EXCHANGER_KEY})
        ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException;
        /**
         * 获取Client
         */
        @Adaptive({Constants.EXCHANGER_KEY})
        ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException;
    }
    当然底层还是依赖的Transporter,这里就不再重复说了。Handler 回到数据流上,请求到达后,经过协议解析和对象的反序列化,以Request对象的形式到达ExchangeHandler, 现在看下该接口:
    public interface ExchangeHandler extends ChannelHandler, TelnetHandler {
        /**
         * reply.
         */
        CompletableFuture<Object> reply(ExchangeChannel channel, Object request) throws RemotingException;
    }
    从接口可以看到,在收到请求后,handler负责回复Response,就是说handler负责调用接口的实现类,然后将结果通过网络返回。

    服务暴露

    请求到达服务端后,需要调用本地的接口实现类。还记得上一篇中讲到的Invoker吗?它是对调用的封装接口,在服务提供方,同样是用的它,只是这次执行invoke()方法的时候是调用的本地实现类。

    Exporter

    Invoker调用本地方法,首要的自然是找到本地实现类在什么地方,这时候就需要引入另外一个接口Exporter。
    public interface Exporter<T> {
        /**
         * 获取Invoker
         */
        Invoker<T> getInvoker();
        /**
         * 取消接口暴露
         */
        void unexport();
    } 
    Exporter代表本地接口服务的暴露。可以这么理解,本地有个接口的实现,我想让其它服务能够远程调用到,那就需要按照一定的协议注册成一个Exporter,否则即使远程发送请求过来要求访问该实现,Dubbo也是不允许的。 可以看到,通过Exporter是可以拿到Invoker的,对这个invoker的执行调用的就是本地接口实现。Dubbo中一个接口实现可以以多种协议暴露,调用的Protocol接口的export方法,默认自然是DubboProtocol中的DubboExporter。
    @SPI("dubbo")
    public interface Protocol {
        //暴露服务接口
        @Adaptive
        <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
    
         //获取接口调用的Invoker
        @Adaptive
        <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
    } 
    看完上面几个接口,我们把关系捋一下。在服务启动的后,根据服务的配置,Dubbo会将一个接口的实现在指定的协议上暴露成一个Exporter,Exporter中封装了一个本地调用的Invoker。 ExchangeHandler收到请求后,从请求中拿到协议,接口名、方法名以及反序列化后的参数,所有这些基本上都封装在一个RpcInvocation中。Handler到指定协议中找接口的Exporter,找到后就可以获取到Invoker,invoker执行时会调用本地实现类的方法。

    本地调用

    上面讲到发起调用本地方法的Invoker,Dubbo也有两种实现方式,一种是用的java的反射调用,一种是用javaassist生成一个Invoker的实现类,在生成的类中直接引用接口实现。显然后一种性能更好,Dubbo默认也是用的后一种方式。 获取Invoker的方法也是在ProxyFactory接口中。
    @SPI("javassist")
    public interface ProxyFactory {
        /**
         * 创建远程接口的代理,Consumer用
         */
        @Adaptive({PROXY_KEY})
        <T> T getProxy(Invoker<T> invoker) throws RpcException;
        /**
         * 创建本地调用Invoker的代理,Provider用
         */
        @Adaptive({PROXY_KEY})
        <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
    } 

    Provider端总结

    一图胜千言,对应RPC的图画下Dubbo Provider这一端的模块关系。
  • 相关阅读:
    Mongoose 校验参数
    meta大全
    go并发之WaitGroup
    用Tasker实现收到Android手机短信自动转发到微信
    不用双卡iPhone,仅需五步,老iOS手机自动给你转发短信
    怎样选择莫代尔秋衣裤
    关于ROS的dst-nat和src-nat的理解,和公司的一个案例以及解决方案
    关于ADSL拨号多拨跟运营商AC服务器之间的关系和一些技巧,群里大神给的经验
    查询网站的dns,get,劫持检测等等
    zabbix自定义key类型之计算(Calculated items) 在流量曲线图里,把各个item的值叠加的方法
  • 原文地址:https://www.cnblogs.com/johnvwan/p/15647439.html
Copyright © 2020-2023  润新知