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); }