• Home
  • Articles
    • 日志
    • 妍小言
    • 舒小书
    • 浩然说
    • 生活日记
  • All Tags

netty学习整理

08 Jun 2018

Reading time ~1 minute

以TCP协议,NIO为基础学习研究。下文中如无特殊说明,channel都指的是netty channel。

以下是netty client启动代码

public class Client {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup eventLoop = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(eventLoop);
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3 * 1000);
        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline()
                        .addLast("decoder", new ObjectDecoder(ClassResolvers.cacheDisabled(getClass().getClassLoader()))) // in 1
                        .addLast("encoder", new ObjectEncoder())// out 3
                        .addLast("idleStateHandler", new IdleStateHandler(0, 1, 0))
                        .addLast(new ClientIdleHandler());

            }
        });

        ChannelFuture future = bootstrap.connect("localhost", 12345);
        future.sync().channel().closeFuture().sync();
    }
}

线程模型

  • AbstractBootstrap:用来初始化一个channel并向EventLoopGroup中注册这个channel。
  • NioEventLoopGroup:初始化EventLoop集合,默认大小为系统核数 * 2,并初始化chooser实现,用来将注册过来的channel选择一个EventLoop并实际注册到之中。
  • NioEventLoop:继承了Executor接口,可以管理多个netty channel,并open了一个selector,通过selector来管理多个java NIO channel。

简述管道注册流程

简单记录下自己阅读netty代码的总结。

        io.netty.bootstrap.Bootstrap#doResolveAndConnect
  • AbstractBootstrap负责初始化一个channel并注册,初始化是会open一个java nio channel,但此时并不会connect。

      io.netty.channel.MultithreadEventLoopGroup#register(io.netty.channel.Channel)
    
  • AbstractBootstrap获取配置的EventLoopGroup并向其注册初始化的channel。

      io.netty.util.concurrent.MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, java.util.concurrent.Executor, io.netty.util.concurrent.EventExecutorChooserFactory, java.lang.Object...)
    
  • EventLoopGroup初始化时做了两件事:
    1. 初始化多个EventLoop。
    2. 初始化chooser,用来选择返回一个EventLoop实例。
      io.netty.util.concurrent.EventExecutorChooserFactory.EventExecutorChooser#next
    
  • EventLoopGroup调用next()方法,通过chooser获取到EventLoop实例并调用其注册方法。

      io.netty.channel.AbstractChannel.AbstractUnsafe#register
    
  • 将EventLoop和ChannelPromise都注册到channel中。

  • EventLoop启动一个线程来维护channel的事件,如线程已启动,则不重复启动。

      io.netty.channel.nio.AbstractNioChannel#doRegister
    
  • 将channel维护的java nio channel注册进EventLoop维护的selector,并将该channel作为attachment同时注册到SelectionKey中并触发registered事件。

      io.netty.bootstrap.Bootstrap#doResolveAndConnect0
    
  • channel注册之后会触发绑定的listener,会调用直行connect方法,如果链接成功,则触发active事件。

      io.netty.channel.nio.NioEventLoop#processSelectedKey(java.nio.channels.SelectionKey, io.netty.channel.nio.AbstractNioChannel)
    
  • 对于通道的读取则会走到NioEventLoop的processSelectedKey方法,会同时管理channel的数据读取和通道的关闭。

待补充

  1. netty监听模式
  2. EventLoop线程执行模式。


netty