美文网首页
2019-03-09 Netty组件

2019-03-09 Netty组件

作者: ssochi | 来源:发表于2019-03-09 16:43 被阅读0次

Netty的启动代码

EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap(); // (2)
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class) // (3)
             .childHandler(new ChannelInitializer<SocketChannel>() { // (4)
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ch.pipeline().addLast(new DiscardServerHandler());
                 }
             })
                    .option(ChannelOption.SO_BACKLOG, 128)          // (5)
                    .childOption(ChannelOption.SO_KEEPALIVE, true); // (6)

            // Bind and start to accept incoming connections.
            ChannelFuture f = b.bind(port).sync(); // (7)
    
            // Wait until the server socket is closed.
            // In this example, this does not happen, but you can do that to gracefully
            // shut down your server.
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }

NioEventLoop

NioEventLoop(启动时)是一个独立运行的线程,NioEventLoop内持有一个Selector,线程首要执行对Selector的轮询工作,若轮询没有结果便去执行Task队列中的Task。NioEventLoop是延迟启动的,因此若一个NioEventLoop未执行任何任务,那么NioEventLoop不会去启动一个线程。

NioEventLoopGroup

NioEventLoopGroup持有多个NioEventLoop,可以把它看成一个线程池。使用NioEventLoopGroup::next 可以获取一个NioEventLoop,这使得我们能够重复使用NioEventLoop。

bossGroup

bossGroup本质上是一个NioEventLoopGroup,将它注册到ServerBootstrap中后,它将会被分配给NioServerSocketChannel。也就是说bossGroup会分配一个NioEventLoop来处理接收到的连接请求。(bossGroup是一个线程池,而使用示例代码时,服务只绑定了一个端口,因此也只有一个NioServerSocketChannel,那么bossGroup实际上只分配出了一个线程。因此猜测在实际使用中,若在一个进程中监听多个端口,那么可以复用bossGroup)

workerGroup

workerGroup本质上也是一个NioEventLoopGroup,当有新的NioSocketChannel注册时,NioServerSocketChannel会将workerGroup的一个EventLoop分配给这个channel,之后这个channel的所有行为都会在这个eventLoop中执行。workerGroup是一个线程池,但它的线程数是有限的,因此NioEventLoopGroup采用了轮换分配的方法,确保各个eventLoop能持有数量相近的channel。这里需要注意的是,每个eventLoop持有一个Selector,而Selector上注册了多个channel,若业务逻辑也在这个eventLoop中执行,那么耗时的操作会阻塞这个Selector下所有的channel的业务执行,是得不偿失的。

Channel

Netty中的Channel是对JDK中的Channel的封装,Channel本身持有一个Pipeline,用于处理Channel中发生的各种事件(register,read,write,flush,etc)。Selector本身持有了Channel,而NioEventLoop持有了Selector,因此整个运行的逻辑是NioEventLoop轮询Selector,收到有效的selectorKey,从key中获取channel,在向channel的管道中发送接收到的事件。

Pipeline

Pipeline是一条调用链,也可以说是拦截器机制,当Pipeline收到一个事件之后会从Head依次发送的Tail。当然可以自定义Pipeline节点来处理各种事件。

ServerBootstrap

启动类

流程

将BossEventLoopGroup,WorkerEventLoopGroup给ServerBootStrap
ServerBootstrap开启一个ServerSocketChannel,并将WorkerEventLoopGroup给channel
ServerBootStrap通过BossEventLoopGroup生成一个eventloop
将ServerSocketChannel注册到这个eventloop上
eventloop获得selector,并将channel关心的事件注册到selector上
之后开始轮询selector

一旦selector收到了事件,便将事件交给ServerSocketChannel
ServerSocketChannel收到了一个连接请求,建立连接,并为连接创建SocketChannel
同时ServerSocketChannel从workerEventLoop中获取一个eventloop
把SocketChannel关心的事件注册到这个eventloop上

这时eventloop创建selector,注册事件,开始轮询
一旦收到事件交给channel
channel获取后,丢到pipeline里,逐层执行
最后到用户定义的IoHandle中

相关文章

网友评论

      本文标题:2019-03-09 Netty组件

      本文链接:https://www.haomeiwen.com/subject/kuyspqtx.html