文章目录
- 1. 入门
- 2. Netty 代码实例
- 3. Netty bind
- 3.1 initAndRegister
- 3.1.1 newChannel, 创建 NioServerSocketChannel
- 3.1.2 init(channel); 初始化 NioServerSocketChannel
- 3.1.3 register 注册channel
- 3.2 doBind0 绑定端口
- 3.3 ServerBootstrapAcceptor
1. 入门
主从Reactor模型 :Acceptor 接收到客户端TCP连接请求并处理完成后, 将新创建的SocketChannel 注册到 I/O线程池 (sub Reactor)传送门
主要步骤:
-
Acceptor
创建ServerSocketChannel
-
Acceptor ServerSocketChannel
绑定端口 -
Acceptor ServerSocketChannel
设置非阻塞 -
Acceptor
创建Selector
,将ServerSocketChannel
注册到Selector
上,监听SelectionKey.OP_ACCEPT
事件 -
Acceptor ServerSocketChannel
设置分发处理器,处理监听到的SelectionKey.OP_ACCEPT
事件,新创建的SocketChannel
分发到到I/O线程池 (sub Reactor)
-
I/O线程池 (sub Reactor)
不断轮训处理SocketChannel
上的读写请求
2. Netty 代码实例
ServerBootstrap:
- 配置
EventLoopGroup
线程组:
需要注意的是, 只绑定一个端口,bossEventLoopGroup
1个就够了, 2个会有一个闲置
- 设置
Channel
类型:NioServerSocketChannel
- 设置
childHandler
的ChannelPipeline
- 绑定端口: 创建
NioServerSocketChannel
, 注册, 绑定端口,ServerSocketChannel
添加分发到子线程组的 handler
3. Netty bind
主要下面两个方法:
-
final ChannelFuture regFuture = initAndRegister();
初始化channel
,并且注册ServerSocketChannel
到bossEventLoopGroup
的 一个EventLoop
的Selector
上 -
doBind0(regFuture, channel, localAddress, promise);
绑定端口号
3.1 initAndRegister
io.netty.bootstrap.AbstractBootstrap#initAndRegister
初始化channel
,并且注册ServerSocketChannel
到 bossEventLoopGroup
的 一个 EventLoop
的 Selector
上
3.1.1 newChannel, 创建 NioServerSocketChannel
- 创建
channel = channelFactory.newChannel();
io.netty.channel.ReflectiveChannelFactory#newChannel
io.netty.channel.socket.nio.NioServerSocketChannel#NioServerSocketChannel
,
-
NioServerSocketChannel
处理连接事件:super(null, channel, SelectionKey.OP_ACCEPT);
-
AbstractNioChannel
: 设置非阻塞ch.configureBlocking(false);
-
AbstractChannel
初始化unsafe、pipeline: unsafe = newUnsafe(); pipeline = newChannelPipeline();
-
DefaultChannelPipeline
:tail = new TailContext(this); head = new HeadContext(this);
3.1.2 init(channel); 初始化 NioServerSocketChannel
初始化 Channel
:io.netty.bootstrap.ServerBootstrap#init
, pipeline
添加 ServerBootstrapAcceptor
是一个异步过程,需要 EventLoop
线程负责执行。而当前 EventLoop
线程该去执行 register0()
的注册流程,所以等到 register0()
执行完之后才能被添加到 Pipeline
当中
- 注册
Channel
:ChannelFuture regFuture = config().group().register(channel);
-
config().group()
就是bossEventLoopGroup
execute
:io.netty.util.concurrent.SingleThreadEventExecutor#execute
addTask(task);
if (!inEventLoop) startThread();
3.1.3 register 注册channel
- 注册
ServerSocketChannel
到bossEventLoopGroup
的一个EventLoop
的Selector
上,监听SelectionKey.OP_ACCEPT
事件
io.netty.channel.SingleThreadEventLoop#register(io.netty.channel.ChannelPromise)
io.netty.channel.AbstractChannel.AbstractUnsafe#register
io.netty.channel.AbstractChannel.AbstractUnsafe#register0
io.netty.channel.nio.AbstractNioChannel#doRegister
- 调用java 的 nio:
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
3.2 doBind0 绑定端口
io.netty.bootstrap.AbstractBootstrap#doBind0
- io.netty.channel.AbstractChannel#bind(java.net.SocketAddress, io.netty.channel.ChannelPromise)
- io.netty.channel.DefaultChannelPipeline#bind(java.net.SocketAddress, io.netty.channel.ChannelPromise)
- io.netty.channel.AbstractChannelHandlerContext#bind(java.net.SocketAddress, io.netty.channel.ChannelPromise)
- io.netty.channel.AbstractChannelHandlerContext#invokeBind
- io.netty.channel.DefaultChannelPipeline.HeadContext#bind
- io.netty.channel.AbstractChannel.AbstractUnsafe#bind
- io.netty.channel.socket.nio.NioServerSocketChannel#doBind 调用java 的 bind
3.3 ServerBootstrapAcceptor
child
就是 workerEventLoopGroup
,socketChannel
注册到 workerEventLoopGroup
进行处理