Bootstrap

dubbo源码分析第十篇一提供者端通信NettyServer

原理图

  • 与dubbo消费者的exchange transport codec基本一致
  • 区别在于 transport层虽都是netty,一个是NioServerSocketChannel,一个是NioSocketChannel
    在这里插入图片描述

源码分析

DubboProtocol.openServer

  • 提供者通信入口
  • createServer创建服务
  private void openServer(URL url) {
        // ip:port 进行server级别的复用
        String key = url.getAddress();
        boolean isServer = url.getParameter(IS_SERVER_KEY, true);
        if (isServer) {
            ExchangeServer server = serverMap.get(key);
            if (server == null) {
            	线程安全
                synchronized (this) {
                    server = serverMap.get(key);
                    if (server == null) {
                        创建server
                        serverMap.put(key, createServer(url));
                    }
                }
            } else {
                server.reset(url);
            }
        }
    }

createServer

  • 调用Exchangers 完成ExchangeServer创建
private ExchangeServer createServer(URL url) {
    ...... 删除url配置参数代码
    ExchangeServer server;
    try {
        server = Exchangers.bind(url, requestHandler);
    } catch (RemotingException e) {
        throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
    }

    ...... 删除其他代码

    return server;
}

通过HeaderExchanger创建ExchangeServer

  • handler结构同nettyclient
  • DecodeHandler不同于DubboCodec,DecodeHandler是更精细化的编解码针对dubbo的rpc业务层面,而DubboCodec针对网络传输层面
DecodeHandlerHeaderExchangeHandlerExchangeHandlerAdapter
进一步完成Request内部的dubbo协议解码 用于方法调用完成请求响应映射查找dubbo exportor集合进行服务调用
public class HeaderExchanger implements Exchanger {
    public static final String NAME = "header";
    @Override
    public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
        return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
    }
}

Transporter完成bind

  • 通过spi选择NettyTransporter
  • NettyTransporter 负责NettyServer构建
public static Server bind(URL url, ChannelHandler... handlers) throws RemotingException {
    return getTransporter().bind(url, handler);
}

public class NettyTransporter implements Transporter {
    public static final String NAME = "netty";

    @Override
    public Server bind(URL url, ChannelHandler listener) throws RemotingException {
        return new NettyServer(url, listener);
    }
}

NettyServer构建

  • 完成handler增强 MultiMessageHandler HeartbeatHandler AllChannelHandler
  • 设置DubboCountCodec和handler装饰者到NettyServer的codec和handler属性
  • doOpen完成netty编排

    public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
      
        super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)));
    }
public AbstractServer(URL url, ChannelHandler handler) throws RemotingException {
    设置codec 和handler属性
    super(url, handler);
    netty编排
    doOpen();
 
}

doOpen实现netty编排

  • 完成codec 和 exchange层handler向netty框架的注入编排
protected void doOpen() throws Throwable {
    bootstrap = new ServerBootstrap();

    bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("NettyServerBoss", true));
    workerGroup = new NioEventLoopGroup(getUrl().getPositiveParameter(IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS),
            new DefaultThreadFactory("NettyServerWorker", true));
    构建NettyServerHandler
    final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this);
    channels = nettyServerHandler.getChannels();

    bootstrap.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
            .childOption(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
            .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
            .childHandler(new ChannelInitializer<NioSocketChannel>() {
                @Override
                protected void initChannel(NioSocketChannel ch) throws Exception {
                    
                    int idleTimeout = UrlUtils.getIdleTimeout(getUrl());
                    构建NettyCodecAdapter
                    NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
                    ch.pipeline()
                            .addLast("decoder", adapter.getDecoder())
                            .addLast("encoder", adapter.getEncoder())
                            .addLast("server-idle-handler", new IdleStateHandler(0, 0, idleTimeout, MILLISECONDS))
                            .addLast("handler", nettyServerHandler);
                }
            });
    // 启动服务端socketchannel
    ChannelFuture channelFuture = bootstrap.bind(getBindAddress());
    channelFuture.syncUninterruptibly();
    channel = channelFuture.channel();

}

总结

  • 结合第九篇,概述dubbo remote模块三层架构[exhcange,transport codec]
  • 介绍编解码器以及各层实现基本作用,handler装饰者结构中,各handler基本作用
  • 介绍dubbo的客户端和服务端的可复用共享模型[ip:port]
;