Netty 框架

    Netty是Reactor模式事件驱动网络框架,Netty不仅用法简单,而且性能和可靠性都很好,所以被很多的中间件作为网络层使用,像dubbo, RocketMQ底层都采用了Netty。
    Netty采用的是Reactor模式,由一个boss线程池充当main reactor,worker线程池充当sub reactor,main reactor负责监听端口,接收socket连接;sub reactor负责socket数据的读写,main reactor将接收的socket连接分配给sub reactor,sub reactor负责管理socket,并调用Handlet处理socket的IO事件。
    Netty为什么这么高效?因为Netty使用了Nio,Nio主要由三部分构成:Channel, Buffer和Selector,相比于Bio服务器,Nio实现了非阻塞io和多路复用,充分利用多CPU的性能,所以Netty具有很好的性能。
    

启动Netty服务器:

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

try {
    ServerBootstrap serverBootstrap = new ServerBootstrap();
    serverBootstrap.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            .childHandler(new ChannelInitializer<SocketChannel>() {
                 //Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ch.pipeline().addLast(new EventHandler());
                 }
            })
            .option(ChannelOption.SO_BACKLOG, 128)
            .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
            .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
            .childOption(ChannelOption.SO_KEEPALIVE, true);

    // bind and start to accept incoming connections.
    ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();

    channelFuture.channel().closeFuture().sync();
} finally {
   workerGroup.shutdownGracefully();
   bossGroup.shutdownGracefully();
}


主要类分析:
类图:

  

ServerBootstrap:
ServerBootstrap启动类,通过初始化boos和worker线程池,创建ServerSocketChannel绑定端口,并初始化ServerSocketChannel配置,启动Socket Server。

关键类和方法:
    1. group(group)
        group方法初始化boss和work工作线程都为group
    2. group(parentGroup, childGroup)
        group方法初始化boss和work工作线程,parentGroup为boss,childGroup为worker
    3. bind( )
        AbstractBootstrap通过bind方法用boss线程绑定端口并返回ChannelFuture
    4. ServerBootstrapAcceptor
        ServerBootstrapAcceptor继承ChannelInboundHandlerAdapter,作为ServerSocketChannel的ChannelHandler处理事件
    5. ServerBootstrapAcceptor channelRead( )
        ServerBootstrapAcceptor的channelRead方法,处理ServerSocketChannel的read事件,将新的连接NioSocketChannel注册到childGroup中,从而实现了boss分配连接到work。

NioEventLoopGroup:
NioEventLoopGroup线程池类,继承MultithreadEventLoopGroup和MultithreadEventExecutorGroup,MultithreadEventExecutorGroup其中包含一个EventExecutor数组,NioEventLoopGroup通过实现newChild( )方法实例一个NioEventLoop工作线程池。关键类和方法:
    1. newChild( )
        newChild方法实现了MultithreadEventExecutorGroup的抽象方法,返回一个NioEventLoop工作
    2. MultithreadEventLoopGroup register(channel)
        MultithreadEventLoopGroup的register一个channel到一个NioEventLoop上
    3. MultithreadEventLoopGroup next( )
        MultithreadEventLoopGroup的next方法返回一个NioEventLoop

NioEventLoop
NioEventLoop线程类,继承SingleThreadEventLoop和SingleThreadEventExecutor,NioEventLoop包含一个Selector负责监听加入的socket事件,SingleThreadEventExecutor包含一个Thread和task队列,execute第一个任务时才会启动工作线程,线程负责依次处理监听事件和任务队列,所以boss只有一个线程,worker有CPU x 2个线程。
关键类和方法:
    1. register(SelectableChannel ch)
        register方法注册一个channel到NioEventLoop的Selector上
    2. run( )
        NioEventLoop线程方法,依次处理Selector上的非IO事件和IO事件
    3. SingleThreadEventExecutor execute(task)
        SingleThreadEventExecutor的execute方法第一次被调用时才会启动本线程

ServerBootstrap: 将AbstractBootstrap.ServerBootstrapAcceptor绑定到ServerChannel

void init(Channel channel) throws Exception {
    Map options = this.options();
    synchronized(options) {
           channel.config().setOptions(options);
    }

    Map attrs = this.attrs();
    synchronized(attrs) {
       Iterator currentChildGroup = attrs.entrySet().iterator();

       while(true) {
           if(!currentChildGroup.hasNext()) {
               break;
           }
           Entry currentChildHandler = (Entry)currentChildGroup.next();
           AttributeKey currentChildOptions = (AttributeKey)currentChildHandler.getKey();
           channel.attr(currentChildOptions).set(currentChildHandler.getValue());
       }
    }

    ChannelPipeline p = channel.pipeline();
    if(this.handler() != null) {
        p.addLast(new ChannelHandler[]{this.handler()});
    } 
    
    final EventLoopGroup currentChildGroup1 = this.childGroup;
    final ChannelHandler currentChildHandler1 = this.childHandler;
    Map var9 = this.childOptions;
    final Entry[] currentChildOptions1;
    synchronized(this.childOptions) {
        currentChildOptions1 =(Entry[])this.childOptions.entrySet().toArray(newOptionArray(this.childOptions.size()));
    }

    var9 = this.childAttrs;
    final Entry[] currentChildAttrs;
    synchronized(this.childAttrs) {
        currentChildAttrs = (Entry[])this.childAttrs.entrySet().toArray(newAttrArray(this.childAttrs.size()));
    }

    /**
     * 将ServerBootstrapAcceptor作为ChannlelHandler绑定到ServerChannel,
     * ServerChannel上的Selector事件将通过ServerBootstrapAcceptor处理。
     */
    p.addLast(new ChannelHandler[]{new ChannelInitializer() {
        public void initChannel(Channel ch) throws Exception {
            ch.pipeline().addLast(new ChannelHandler[]{new ServerBootstrap.ServerBootstrapAcceptor(currentChildGroup1, currentChildHandler1, currentChildOptions1, currentChildAttrs)});
        }
    }}); 
}

 


private static void doBind0(final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) {
    channel.eventLoop().execute(new Runnable() {
        public void run() {
            if(regFuture.isSuccess()) {
                channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            } else {
                promise.setFailure(regFuture.cause());
            }
        }
    });
}


AbstractBootstrap.ServerBootstrapAcceptor:绑定新channel到workGroup

public void channelRead(ChannelHandlerContext ctx, Object msg) {
    final Channel child = (Channel) msg;
    child.pipeline().addLast(new ChannelHandler[]{this.childHandler});
    Entry[] t = this.childOptions;
    int len$ = t.length;

    int i$;
    Entry e;
    for (i$ = 0; i$ < len$; ++i$) {
        e = t[i$];

        try {
            if (!child.config().setOption((ChannelOption) e.getKey(), e.getValue())) {
                ServerBootstrap.logger.warn("Unknown channel option: " + e);
            }
        } catch (Throwable var10) {
            ServerBootstrap.logger.warn("Failed to set a channel option: " + child, var10);
        }
     }

    t = this.childAttrs;
    len$ = t.length;
    for (i$ = 0; i$ < len$; ++i$) {
        e = t[i$];
        child.attr((AttributeKey) e.getKey()).set(e.getValue());
    }
        
    try {
        /**
         * Acceptor接受新的channel后,将channel注册到childGroup中去,
         * childGroup则通过next方法返回一个eventLoop,将channel注册到eventLoop的selector上。
         */
        this.childGroup.register(child).addListener(new ChannelFutureListener() {
            public void operationComplete(ChannelFuture future) throws Exception {
                if (!future.isSuccess()){               
                    ServerBootstrap.ServerBootstrapAcceptor.forceClose(child, future.cause());
                }
            }   
        }); 
    } catch (Throwable var9) {
        forceClose(child, var9);
    }
}


SingleThreadEventExecutors: 启动线程

public void execute(Runnable task) {
    if(task == null) {
        throw new NullPointerException("task");
    } else {
        /**
         * 如果在本线程中,则添加新的任务到eventLoop任务队列;
         * 如果不在本线程中,则检测线程是否启动并添加任务到eventLoop任务队列。
         */
        boolean inEventLoop = this.inEventLoop();
        if(inEventLoop) {
            this.addTask(task);
        } else {
            this.startThread(); 
            this.addTask(task);
            if(this.isShutdown() && this.removeTask(task)) {
                reject();
            }
        }

        if(!this.addTaskWakesUp) {
            this.wakeup(inEventLoop);
        } 
    }
}


NioEventLoop:线程处理

protected void run() {
    while(true) {
        this.oldWakenUp = this.wakenUp.getAndSet(false);

        try {
            /**
             * 如果task队列上有任务,则直接wakeup。
             * 如果task队列上没有任务,则进入select状态,等待事件wakeup。
             * task队列上的任务主要是注册新的Channel。
             */
            if(this.hasTasks()) {
                this.selectNow();
            } else {
                this.select();
                if(this.wakenUp.get()) {
                    this.selector.wakeup();
                }
            }

            /**
             * ioRatio默认为50,nio线程用一半时间处理selector上的事件,一半处理task队列上的任务。
             */
            this.cancelledKeys = 0;
            long t = System.nanoTime();
            this.needsToSelectAgain = false;
            if(this.selectedKeys != null) {
                this.processSelectedKeysOptimized(this.selectedKeys.flip());
            } else {
                this.processSelectedKeysPlain(this.selector.selectedKeys());
            }

            long ioTime = System.nanoTime() - t;
            int ioRatio = this.ioRatio;
            this.runAllTasks(ioTime * (long)(100 - ioRatio) / (long)ioRatio);
            if(this.isShuttingDown()) {
                this.closeAll();
                if(this.confirmShutdown()) {
                    return;
                }
            }
        } catch (Throwable var7) {
            logger.warn("Unexpected exception in the selector loop.", var7);
            
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException var6) {
                   
            }
        }
    }
}

 

转载于:https://my.oschina.net/u/2950586/blog/758747

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值