十:线程与线程池(一)

课程主要内容:

  • 掌握Apache Dubbo线程模型异同
  • 掌握Apache Dubbo线程池异同与选择
  • 了解Apache Dubbo线程数选择

在这里插入图片描述

线程模型

线程模型线程模型作用
All所有消息都派发到线程池,包括请求、响应、连接事件、断开事件、心跳等
Direct所有请求都不派发到线程池,全部在IO线程上直接执行
Message只有请求响应消息派发到线程池
Excution只有请求消息派发到线程池,不含响应
Connection在IO线程上,将连接断开事件放入队列,有序逐个执行

属性配置:

<dubbo:protocol name=“dubbo” port=“29014” dispatcher=“all”/>

源码剖析

在NettyServer与NettyClient的构造方法中都有调用 ChannelHandlers.wrap方法

    //org.apache.dubbo.remoting.transport.netty4.NettyServer#NettyServer
    public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
        // you can customize name and type of client thread pool by THREAD_NAME_KEY and THREADPOOL_KEY in CommonConstants.
        // the handler will be wrapped: MultiMessageHandler(多消息处理)->HeartbeatHandler(心跳处理)->handler
        super(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME), ChannelHandlers.wrap(handler, url));
    }

	//org.apache.dubbo.remoting.transport.netty4.NettyClient#NettyClient
    public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException {
    	// you can customize name and type of client thread pool by THREAD_NAME_KEY and THREADPOOL_KEY in CommonConstants.
    	// the handler will be wrapped: MultiMessageHandler->HeartbeatHandler->handler
    	super(url, wrapChannelHandler(url, ChannelHandlers.wrap(handler, url)));
    }

如下是 ChannelHandlers.wrap方法:

    //
    protected ChannelHandler wrapInternal(ChannelHandler handler, URL url) {
    	//此处获取到配种中的dispatcher属性 调用对应实现的dispatcher的 dispatch方法,每一种dispatcher都对应自己的ChannelHandler
        return new MultiMessageHandler(new HeartbeatHandler(ExtensionLoader.getExtensionLoader(Dispatcher.class)
                .getAdaptiveExtension().dispatch(handler, url)));
    }

因为NettyServer与NettyClient的实现基本一直,所以我们以NettyServer为例进行讲解:

关于何时使用的 我们回到 NettyTransporter 的 bind方法中,(此处由org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#createServer方法调用过来的)

    @Override
    public RemotingServer bind(URL url, ChannelHandler handler) throws RemotingException {
        //创建NettyServer
        return new NettyServer(url, handler);
    }
    public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
        // you can customize name and type of client thread pool by THREAD_NAME_KEY and THREADPOOL_KEY in CommonConstants.
        // the handler will be wrapped: MultiMessageHandler->HeartbeatHandler->handler
        //ChannelHandlers.wrap(handler, url) 方法获取到对应的 handle,并 调用父类构造方法
        super(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME), ChannelHandlers.wrap(handler, url));
    }
    public AbstractServer(URL url, ChannelHandler handler) throws RemotingException {
        //此处不再深入,此处为继续调用父类,一直到AbstractPeer类的构造方法中,将ChannelHandler handler属性赋值
        super(url, handler);
        localAddress = getUrl().toInetSocketAddress();

        String bindIp = getUrl().getParameter(Constants.BIND_IP_KEY, getUrl().getHost());
        int bindPort = getUrl().getParameter(Constants.BIND_PORT_KEY, getUrl().getPort());
        if (url.getParameter(ANYHOST_KEY, false) || NetUtils.isInvalidLocalHost(bindIp)) {
            bindIp = ANYHOST_VALUE;
        }
        bindAddress = new InetSocketAddress(bindIp, bindPort);
        this.accepts = url.getParameter(ACCEPTS_KEY, DEFAULT_ACCEPTS);
        this.idleTimeout = url.getParameter(IDLE_TIMEOUT_KEY, DEFAULT_IDLE_TIMEOUT);
        try {
            //调用NettyServer的doOpen方法,进入
            doOpen();
            if (logger.isInfoEnabled()) {
                logger.info("Start " + getClass().getSimpleName() + " bind " + getBindAddress() + ", export " + getLocalAddress());
            }
        } catch (Throwable t) {
            throw new RemotingException(url.toInetSocketAddress(), null, "Failed to bind " + getClass().getSimpleName()
                    + " on " + getLocalAddress() + ", cause: " + t.getMessage(), t);
        }
        executor = executorRepository.createExecutorIfAbsent(url);
    }
    @Override
    protected void doOpen() throws Throwable {
        bootstrap = new ServerBootstrap();

        bossGroup = NettyEventLoopFactory.eventLoopGroup(1, "NettyServerBoss");
        workerGroup = NettyEventLoopFactory.eventLoopGroup(
                getUrl().getPositiveParameter(IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS),
                "NettyServerWorker");

        //此处会创建Netty所使用的的 Handler 即:NettyServerHandler,类中属性ChannelHandler handler持有了本类,本类实现了ChannelHandler,在父类AbstractPeer中 重写了 连接、取消连接、请求、响应 等一些请求,也是直接调用传入的对应的handle来实现的
        final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this);
        channels = nettyServerHandler.getChannels();

        bootstrap.group(bossGroup, workerGroup)
                .channel(NettyEventLoopFactory.serverSocketChannelClass())
                .option(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
                .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        // FIXME: should we use getTimeout()?
                        int idleTimeout = UrlUtils.getIdleTimeout(getUrl());
                        NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
                        if (getUrl().getParameter(SSL_ENABLED_KEY, false)) {
                            ch.pipeline().addLast("negotiation",
                                    SslHandlerInitializer.sslServerHandler(getUrl(), nettyServerHandler));
                        }
                        ch.pipeline()
                                .addLast("decoder", adapter.getDecoder())
                                .addLast("encoder", adapter.getEncoder())
                                .addLast("server-idle-handler", new IdleStateHandler(0, 0, idleTimeout, MILLISECONDS))
                                //此处将 nettyServerHandler加入到pipeline中,用于具体业务的执行调用
                                .addLast("handler", nettyServerHandler);
                    }
                });
        // bind
        ChannelFuture channelFuture = bootstrap.bind(getBindAddress());
        channelFuture.syncUninterruptibly();
        channel = channelFuture.channel();

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值