Netty服务端是如何一点一点被带动起来的
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
public class Server {
public static void main(String[] args) throws Exception {
// 这个线程用于接收客户端的连接
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
// 这4个线程用于处理IO读写
EventLoopGroup workerGroup = new NioEventLoopGroup(8);
// 这8个线程用于业务处理
EventLoopGroup businessGroup = new NioEventLoopGroup(8);
ServerBootstrap serverBootstrap = new ServerBootstrap();
try {
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) {
ChannelPipeline channelPipeline = ch.pipeline();
channelPipeline.addLast(new StringEncoder());
channelPipeline.addLast(new StringDecoder());
channelPipeline.addLast(businessGroup, new ServerInHandler());
}
});
// bind绑定
ChannelFuture channelFuture = serverBootstrap.bind("127.0.0.1", 8080).sync();
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
以上代码虽不能作为真正的服务端生产代码, 麻雀虽小五脏俱全, 它足以可以说明本篇所要阐述的过程.
Netty服务端启动的导火索就从这个bind方法开始了.
首先要说明一点的是,NioServerSocketChannel它会经历创建-初始化-注册-绑定这4大过程.
NioEventLoop它会经历创建-启动-执行这3大过程.
这4+3=7个过程完成之后, 服务端也就启动起来了.
在执行bind方法之前, NioEventLoop已经完成了创建. (已经执行过的使用绿色表示). 它是通过EventLoopGroup bossGroup = new NioEventLoopGroup(1)被创建的.
NioEventLoop要想启动起来, 是由NioServerSocketChannel在注册的时候被启动起来的.
在执行bind方法的过程中, 首先会来到第一个重要的地方, 那就是创建NioServerSocketChannel.
源码位置: io.netty.bootstrap.AbstractBootstrap#initAndRegister
图片.png在创建的过程, 主要创建了以下几个属性
图片.pngid,unsafe,pipeline,config等.
接下来就是初始化操作,这里面有个比较重要的操作
图片.png 图片.png到目前为止,内存里有以下几个主要类
图片.png继续看重要的NioServerSocketChannel的注册功能
图片.png 图片.png 图片.png这个时候, NioEventLoop里就有了一个与之绑定的唯一线程, 同时队列里面有个注册任务. Thread就会取出注册任务并执行.
这个注册任务会走到如下地方
图片.png 图片.png
目前阶段会形成如下结构
图片.png注册完成之后,接下来就是绑定操作.
图片.png总之一句话, 注册操作要在绑定操作之前, 绑定操作必须在后面.
图片.png绑定完成之后,会'激活'NioServerSocketChannel的ACCEPT事件,就可以接收客户端的请求了.
最后的结构图,请再熟悉下
图片.png