Dubbo源码分析----网络通信相关

在暴露服务,执行到DubboProtocol的export方法的时候,会调用openServer方法,从这里开始,就是Dubbo开启请求监听的地方

    private void openServer(URL url) {
        // find server.
        String key = url.getAddress();
        //client 也可以暴露一个只有server可以调用的服务。
        boolean isServer = url.getParameter(Constants.IS_SERVER_KEY,true);
        if (isServer) {
            ExchangeServer server = serverMap.get(key);
            if (server == null) {
                serverMap.put(key, createServer(url));
            } else {
                //server支持reset,配合override功能使用
                server.reset(url);
            }
        }
    }
    private ExchangeServer createServer(URL url) {
        //默认开启server关闭时发送readonly事件
        url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString());
        //默认开启heartbeat
        url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));
        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);

        url = url.addParameter(Constants.CODEC_KEY, Version.isCompatibleVersion() ? COMPATIBLE_CODEC_NAME : DubboCodec.NAME);
        ExchangeServer server;
        try {
            server = Exchangers.bind(url, requestHandler);
        } catch (RemotingException e) {
            throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
        }
        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.bind

    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");
        return getExchanger(url).bind(url, handler);
    }

根据Dubbo扩展机制知道getExchange获取到的是HeaderExchanger,其bind方法如下

    public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
        return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
    }

从这里会发现,Server和Handler都使用了装饰者模式,为其扩展了很多功能。后面会发现源码中已经在外面包了很多层,提供了很多新的功能
Handler:
1. DecodeHandler:提供了编码解码的功能
2. DecodeHandler:提供数据校验,异常处理,已经将Channel转换成ExchangeChannel

Channel主要是底层的通信类,内部负责利用netty进行通信,而ExchangeChannel在通信方法前后提供了对象的转换,校验的功能。Server那边同理

接下来看下Transporters.bind方法,这之前看到类上有个注释

Transporter facade. (API, Static, ThreadSafe)

可见Transporters主要是获取Server和Client的工厂类,主要为了统一出口,屏蔽内部实现细节,只需要给外面提供Server或者Client的对象就可以了,内部使用什么实现外部可以不用管
然后看下方法

    public static Server bind(URL url, ChannelHandler... handlers) throws RemotingException {
        ....
        ChannelHandler handler;
        if (handlers.length == 1) {
            handler = handlers[0];
        } else {
            handler = new ChannelHandlerDispatcher(handlers);
        }
        return getTransporter().bind(url, handler);
    }

Transporter是传输层的对象,目前有netty,mina和Grizzly3种实现,根据扩展机制,得到的是NettyTransporter,其bind方法返回NettyServer对象,看下NettyServer的继承结构
image.png
调用NettyServer的构造方法时会先调用父类的

    public AbstractPeer(URL url, ChannelHandler handler) {
        ....
        this.url = url;
        this.handler = handler;
    }
    public AbstractServer(URL url, ChannelHandler handler) throws RemotingException {
        super(url, handler);
        ....
        try {
            doOpen();
            ....
        } catch (Throwable t) {
            ....
        }
        if (handler instanceof WrappedChannelHandler ){
            executor = ((WrappedChannelHandler)handler).getExecutor();
        }
    }
    public AbstractEndpoint(URL url, ChannelHandler handler) {
        super(url, handler);
        this.codec = getChannelCodec(url);
        this.timeout = url.getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
        this.connectTimeout = url.getPositiveParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT);
    }
  1. AbstractPeer:属性初始化
  2. AbstractEndpoint:也是属性初始化
  3. AbstractServer:真正初始化网络通信的地方,实现在NettyServer的doOpen方法中
    @Override
    protected void doOpen() throws Throwable {
        NettyHelper.setNettyLoggerFactory();
        ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
        ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
        ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS));
        bootstrap = new ServerBootstrap(channelFactory);

        final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
        channels = nettyHandler.getChannels();
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec() ,getUrl(), NettyServer.this);
                ChannelPipeline pipeline = Channels.pipeline();
                /*int idleTimeout = getIdleTimeout();
                if (idleTimeout > 10000) {
                    pipeline.addLast("timer", new IdleStateHandler(timer, idleTimeout / 1000, 0, 0));
                }*/
                pipeline.addLast("decoder", adapter.getDecoder());
                pipeline.addLast("encoder", adapter.getEncoder());
                pipeline.addLast("handler", nettyHandler);
                return pipeline;
            }
        });
        channel = bootstrap.bind(getBindAddress());
    }

其他先不看,这里主要看nettyHandler,熟悉Netty的看到这就知道请求会经过NettyHandler,逻辑的处理就是在这里面了,当然最后会调用到在DubboProtocol里初始化的RequestHandler
到这里,网络通信部分就结束了,这里涉及的类很多,整个获取Server以及初始化的流程如下
初始化.png
这仅仅是Server的初始化过程,Client的初始化类似

猜你喜欢

转载自blog.csdn.net/u013160932/article/details/79339739