netty学习2


在EventLoopGroup执行期间:

DefaultThreadFactory$DefaultRunnableDecorator.run()  

 private static final class DefaultRunnableDecorator implements Runnable
    {

        private final Runnable r;
        //与Apache mina一样,包装线程
        DefaultRunnableDecorator(Runnable r)
        {
            this.r = r;
        }

        @Override
        public void run()
        {
            try
            {
                r.run();  //在服务器启动时,启动的线程.来执行IO Accept操作。
            }
            finally
            {
                FastThreadLocal.removeAll();
            }
        }
    }



NioEventLoop.run()  线程逻辑方法地方


    protected void run()
    {
        for (;;)   //线程中无限循环来处理
        {
            boolean oldWakenUp = wakenUp.getAndSet(false);
            try {
                if (hasTasks())
                {
                    selectNow();
                }
                else
                {
                    select(oldWakenUp);

                    // 'wakenUp.compareAndSet(false, true)' is always evaluated
                    // before calling 'selector.wakeup()' to reduce the wake-up
                    // overhead. (Selector.wakeup() is an expensive operation.)
                    //
                    // However, there is a race condition in this approach.
                    // The race condition is triggered when 'wakenUp' is set to
                    // true too early.
                    //
                    // 'wakenUp' is set to true too early if:
                    // 1) Selector is waken up between 'wakenUp.set(false)' and
                    //    'selector.select(...)'. (BAD)
                    // 2) Selector is waken up between 'selector.select(...)' and
                    //    'if (wakenUp.get()) { ... }'. (OK)
                    //
                    // In the first case, 'wakenUp' is set to true and the
                    // following 'selector.select(...)' will wake up immediately.
                    // Until 'wakenUp' is set to false again in the next round,
                    // 'wakenUp.compareAndSet(false, true)' will fail, and therefore
                    // any attempt to wake up the Selector will fail, too, causing
                    // the following 'selector.select(...)' call to block
                    // unnecessarily.
                    //
                    // To fix this problem, we wake up the selector again if wakenUp
                    // is true immediately after selector.select(...).
                    // It is inefficient in that it wakes up the selector for both
                    // the first case (BAD - wake-up required) and the second case
                    // (OK - no wake-up required).

                    if (wakenUp.get()) {
                        selector.wakeup();
                    }
                }

                cancelledKeys = 0;
                needsToSelectAgain = false;
                final int ioRatio = this.ioRatio;
                if (ioRatio == 100)
                {
                    processSelectedKeys();
                    runAllTasks();
                }
                else
                {
                    final long ioStartTime = System.nanoTime();

                    processSelectedKeys();

                    final long ioTime = System.nanoTime() - ioStartTime;
                    runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
                }

                if (isShuttingDown()) {
                    closeAll();
                    if (confirmShutdown()) {
                        break;
                    }
                }
            } catch (Throwable t) {
                logger.warn("Unexpected exception in the selector loop.", t);

                // Prevent possible consecutive immediate failures that lead to
                // excessive CPU consumption.
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // Ignore.
                }
            }
        }
    }



    private void processSelectedKeys()
    {
        if (selectedKeys != null)
        {
            //当调用完成select函数,对完成IO读写状态socket进行处理
            processSelectedKeysOptimized(selectedKeys.flip());  //SelectionKey[1024] 参数最大为1024.与windows底层有关
        } else {
            processSelectedKeysPlain(selector.selectedKeys());
        }
    }




 private void processSelectedKeysOptimized(SelectionKey[] selectedKeys)
    {
        for (int i = 0;; i ++)
        {
            final SelectionKey k = selectedKeys[i]; 
            if (k == null)
            {
                break;
            }
            selectedKeys[i] = null;
            //对于SelectionKey相关联的socket进行处理
            final Object a = k.attachment();

            if (a instanceof AbstractNioChannel)  //此时处理事情是public static final int OP_ACCEPT = 1 << 4; (SelectionKey.OP_ACCEPT    interestOps    16    )socket接入事件
            {
                processSelectedKey(k, (AbstractNioChannel) a);
            }

}

NioEventLoop.processSelectedKey(SelectionKey, AbstractNioChannel)


AbstractNioMessageChannel$NioMessageUnsafe.read()  该方法内部处理数据读取操作。


    private final class NioMessageUnsafe extends AbstractNioUnsafe
    {
       //申请缓冲区用于存储临时
        private final List<Object> readBuf = new ArrayList<Object>();

        @Override
        public void read()
        {
            final ChannelConfig config = config();
            if (!config.isAutoRead() && !isReadPending())
            {
                removeReadOp();
                return;
            }
            //每次读取最大数量
            final int maxMessagesPerRead = config.getMaxMessagesPerRead();
            final ChannelPipeline pipeline = pipeline();
            boolean closed = false;
            Throwable exception = null;
            try {
                try
                {
                    for (;;)
                    {
                        int localRead = doReadMessages(readBuf);
                        if (localRead == 0)
                        {
                            break;
                        }
                        if (localRead < 0)
                        {
                            closed = true;
                            break;
                        }

                        // stop reading and remove op
                        if (!config.isAutoRead())
                        {
                            break;
                        }

                        if (readBuf.size() >= maxMessagesPerRead)
                        {
                            break;
                        }
                    }
                } catch (Throwable t) {
                    exception = t;
                }
                setReadPending(false);
                int size = readBuf.size();
                //ChannelPipeline中Handler对数据进行处理
                for (int i = 0; i < size; i ++)
                {        //通知Handler处理每次读取的数据。由于在这里是没有判断分包处理的。所以,在Handler中需要对分包进行处理
                         pipeline.fireChannelRead(readBuf.get(i));
                }

                readBuf.clear();
                pipeline.fireChannelReadComplete();

          
        
                }
            }
        }
    }  





在ChannelPipeline类中,初始化Handler时候,ServerBootstrap中内部类ServerBootstrapAcceptor作为Handler


ServerBootstrap$ServerBootstrapAcceptor.channelRead(ChannelHandlerContext, Object)


    private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter
    {

        private final EventLoopGroup childGroup;
        private final ChannelHandler childHandler;
        private final Entry<ChannelOption<?>, Object>[] childOptions;
        private final Entry<AttributeKey<?>, Object>[] childAttrs;

        ServerBootstrapAcceptor
        (
                EventLoopGroup childGroup, ChannelHandler childHandler,
                Entry<ChannelOption<?>, Object>[] childOptions, Entry<AttributeKey<?>, Object>[] childAttrs) {
            this.childGroup = childGroup;
            this.childHandler = childHandler;
            this.childOptions = childOptions;
            this.childAttrs = childAttrs;
        }
        //在inbound中对读取消息进行读取
        @Override
        @SuppressWarnings("unchecked")
        public void channelRead(ChannelHandlerContext ctx, Object msg)
        {


            final Channel child = (Channel) msg;//child    NioSocketChannel
            child.pipeline().addLast(childHandler);

            for (Entry<ChannelOption<?>, Object> e: childOptions)
            {
                try {
                    if (!child.config().setOption((ChannelOption<Object>) e.getKey(), e.getValue())) {
                        logger.warn("Unknown channel option: " + e);
                    }
                } catch (Throwable t) {
                    logger.warn("Failed to set a channel option: " + child, t);
                }
            }

            for (Entry<AttributeKey<?>, Object> e: childAttrs)
            {
                child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
            }

            try
            {
               //NioSocketChannel 在Acceptor线程中,注册NioSocketChannel和EventLoopGroup相关联。

              //到此处为止,Acceptor线程完成NioSocketChannel和EventLoopGroup相关联的任务。

             //由此而知,Netty 线程模型和Apache Mina线程模型一样

                  childGroup.register(child).addListener(new ChannelFutureListener()
                {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception
                    {
                        if (!future.isSuccess()) {
                            forceClose(child, future.cause());
                        }
                    }
                });
            } catch (Throwable t) {
                forceClose(child, t);
            }
        }

        private static void forceClose(Channel child, Throwable t) {
            child.unsafe().closeForcibly();
            logger.warn("Failed to register an accepted channel: " + child, t);
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            final ChannelConfig config = ctx.channel().config();
            if (config.isAutoRead()) {
                // stop accept new connections for 1 second to allow the channel to recover
                // See https://github.com/netty/netty/issues/1328
                config.setAutoRead(false);
                ctx.channel().eventLoop().schedule(new Runnable() {
                    @Override
                    public void run() {
                       config.setAutoRead(true);
                    }
                }, 1, TimeUnit.SECONDS);
            }
            // still let the exceptionCaught event flow through the pipeline to give the user
            // a chance to do something with it
            ctx.fireExceptionCaught(cause);
        }
    }




















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值