dubbo源码阅读-远程暴露(七)之Exchangers

接口定义

@SPI(HeaderExchanger.NAME)//缺省值为header

public interface Exchanger {

    /**
     * bind.
     *
     * @param url
     * @param handler
     * @return message server
     */
    @Adaptive({Constants.EXCHANGER_KEY}) //带有参数exchanger
    ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException;

    /**
     * connect.
     *
     * @param url
     * @param handler
     * @return message channel
     */
    @Adaptive({Constants.EXCHANGER_KEY})//带参数exchanger
    ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException;

}

 

类图

 

 

说明

我们接着服务暴露开始看《dubbo源码阅读-服务暴露(七)之远程暴露(dubbo)》

private ExchangeServer createServer(URL url) {
        // send readonly event when server closes, it's enabled by default
        // // 服务器关闭时发送readonly事件,默认情况下启用
        url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString());
        // enable heartbeat by default
        //// 心跳默认间隔一分钟
        url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));
        //// 获得远程通讯服务端实现方式,默认用netty
        String str = url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_SERVER);

        if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str))
            throw new RpcException("Unsupported server type: " + str + ", url: " + url);
        //添加编解码器DubboCodec实现
        url = url.addParameter(Constants.CODEC_KEY, DubboCodec.NAME);
        ExchangeServer server;
        try {
            // <1>启动服务器并暴露服务 内部会启动netty服务暴露服务
            server = Exchangers.bind(url, requestHandler);
        } catch (RemotingException e) {
            throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
        }
        // // 获得客户端侧设置的远程通信方式 client
        str = url.getParameter(Constants.CLIENT_KEY);
        if (str != null && str.length() > 0) {
            Set<String> supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();
            if (!supportedTypes.contains(str)) {
                throw new RpcException("Unsupported client type: " + str);
            }
        }
        return server;
    }

Exchangers

com.alibaba.dubbo.remoting.exchange.Exchangers#bind

<1>bind

 /**
     * 这个时候的
     * @param url 暴露的url
     * @param handler 为com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#requestHandler 成员变量 匿名实现
     * @return
     * @throws RemotingException
     */
    public static ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        }
        if (handler == null) {
            throw new IllegalArgumentException("handler == null");
        }
        url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange");
        /**
         *<2>获取Exchange
         *<5>调用bind 方法
         */
        return getExchanger(url).bind(url, handler);
    }

<2>getExchanger

com.alibaba.dubbo.remoting.exchange.Exchangers#bind

->

com.alibaba.dubbo.remoting.exchange.Exchangers#getExchanger

public static Exchanger getExchanger(URL url) {
        //从参数获得exchanger 如果没有取默认header
        String type = url.getParameter(Constants.EXCHANGER_KEY, Constants.DEFAULT_EXCHANGER);
        //<3>SPI获取对应的Exchange
        return getExchanger(type);
    }

<3>getExchanger

com.alibaba.dubbo.remoting.exchange.Exchangers#bind

->

com.alibaba.dubbo.remoting.exchange.Exchangers#getExchanger

->

com.alibaba.dubbo.remoting.exchange.Exchangers#getExchanger

 public static Exchanger getExchanger(String type) {
        //SPI扩展点  默认取的header 所以这里返回的是 com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchanger
        return ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type);
    }

HeaderExchanger

<5>bind

com.alibaba.dubbo.remoting.exchange.Exchangers#bind

->

com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchanger#bind

  @Override
    public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
        //1. handler 会再次经过2层包装,增加功能 注:源头handler是com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#requestHandler
        ChannelHandler h  = new DecodeHandler(new HeaderExchangeHandler(handler));
        //2. Transports 操作会启动netty 监听端口,配置序列化实现,https://www.cnblogs.com/LQBlog/p/12517551.html#autoid-4-0-0
        Server s = Transporters.bind(url,h);
        /**
         * <6>HeaderExchangeServer: 会对nettyServer 进行包装, 主要增加2个功能:
         *
         *     a. 对channel进行 空闲时间检测,超过则关闭连接,节省资源。
         *
         *     b. 如果server关闭,则发送消息给client端,不再发送请求到该server。
         */
        return new HeaderExchangeServer( s);
    }
posted @ 2020-03-18 14:28  意犹未尽  阅读(431)  评论(0编辑  收藏  举报