以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初始化时做了两件事:
- 初始化多个EventLoop。
- 初始化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的数据读取和通道的关闭。
待补充
- netty监听模式
- EventLoop线程执行模式。