**1.服务端启动整体流程及关键方法**
**(1)关键方法**
**(2)整体流程**
**(1)关键方法**
一.EventLoopGroup
服务端的线程模型外观类,Netty的线程模型是事件驱动的。也就是说,这个线程要做的事情就是不停地检测IO事件、处理IO事件、执行任务,并且不断重复这三个步骤。
二.ServerBootstrap
服务端的一个启动辅助类,通过给它设置一系列参数来绑定端口启动服务。
三.group(bossGroup, workerGroup)
设置服务端的线程模型,bossGroup的作用就是不断接收新的连接,并将新连接交给workerGroup来进行处理。
四.channel(NioServerSocketChannel.class)
设置服务端的IO类型为NIO,Netty是通过指定Channel的类型来指定IO类型的。Channel是Netty的一大组件,一个Channel就是一个连接或者一个服务端的bind动作。
五.handler()
表示在服务端的启动过程中,需要经过哪些流程。
六.childHandler()
设置ChannleHandler来处理每个连接上的数据。
七.ChannelFuture f = b.bind(8888).sync()
绑定端口并进行同步等待。绑定端口8888,等服务端启动完毕,才会进入下一行代码。
八.f.channel().closeFuture().sync()
等待服务端关闭端口绑定,这里的作用其实就是让程序不会退出。
九.bossGroup.shutdownGracefully()
关闭事件循环,关闭之后,main方法就结束了。
**(2)整体流程**
**一.创建ServerBootstrap实例**
ServerBootstrap是Netty服务端的启动辅助类,它提供了一系列方法用于设置服务端启动相关的参数。底层通过门面模式对各种能力进行抽象和封装,以让用户少和底层API交互,降低开发难度。ServerBootstrap只有一个无参的构造函数,它使用了Builder模式来处理参数过多的问题。
**二.设置并绑定Reactor线程池**
Netty的Reactor线程池是EventLoopGroup,而EventLoopGroup实际就是EventLoop的数组。EventLoop的职责是处理所有注册到本线程多路复用器Selector上的Channel。Selector的轮询操作是由其绑定的EventLoop线程run()方法驱动的,在一个循环体内循环执行。
**三.设置并绑定服务端Channel**
由于NIO服务端需要创建ServerSocketChannel,而Netty对NIO类库进行了封装,所以对应的就是NioServerSocketChannel。
Netty的ServerBootstrap方法提供了channel()方法用于指定服务端的Channel类型。Netty是通过工厂类(ServerBootstrap的父类AbstractBootstrap的ReflectiveChannelFactory实例),利用反射创建NioServerSocketChannel对象的。由于启动时才调用,所以该反射对运行时的性能没有影响。
**四.创建并初始化ChannelPipeline**
ChannelPipeline不是NIO服务端必需的,它本质是一个负责处理网络事件的职责链。ChannelPipeline这个职责链会负责管理和执行ChannelHandler。网络事件以事件流的形式在ChannelPipeline中流转,由ChannelPipeline根据ChannelHandler的执行策略来调度执行。
**五.添加并设置ChannelHandler**
ChannelHandler是Netty提供给用户定制和扩展的关键接口。利用ChannelHandler用户可以完成大多数的功能定制,如消息编解码、心跳、安全认证、流量控制和流量整形。
**六.绑定并启动监听端口**
在绑定监听端口之前,系统会做一系列的初始化和检测工作。完成之后便会启动监听端口,并将ServerSocketChannel注册到Selector上,然后监听客户端连接。
**七.Selector轮询**
由Reactor线程NioEventLoop负责调度和执行Selector轮询操作,选择准备就绪的Channel集合。
**八.执行ChannelPipeline和ChannelHandler**
当轮询到准备就绪的Channel之后,就由Reactor线程NioEventLoop执行ChannelPipeline的相应方法。即ChannelPipeline会根据网络事件的类型调度并执行ChannelHandler,最终执行Netty自带的ChannelHandler或用户定制的ChannelHandler。
**典型的网络事件有:**
一.channelRegistered() 链路注册
二.channelActive() 链路激活
三.channelInActive() 链路断开
四.channelRead() 接收到请求消息
五.channelReadComplete() 处理完请求消息
六.exceptionCaugh() 链路发生异常
**常用的ChannelHandler有:**
一.ByteToMessageCodec 消息编解码Handler
二.LoggingHandler 码流日志打印Handler
三.SslHandler SSL安全认证Handler
四.IdleStateHandler 链路空闲检测Handler
五.LengthFieldBasedFrameDecoder 基于长度域的半包解码Handler
六.ChannelTrafficShapingHandler 进行流量整形的Handler
七.Base64Decoder和Base64Encoder Base64编解码Handler
**2.服务端启动的核心步骤**
**(1)由启动辅助类的外观接口实现启动**
**(2)启动辅助类的bind()方法**
**(3)启动辅助类的initAndRegister()方法**
**(4)服务端启动的4个核心步骤**
**(1)由启动辅助类的外观接口实现启动**
用户给启动辅助类ServerBootstrap设置好参数后,会通过它的外观接口来实现启动。
```csharp
b.bind(8888).sync();
```
**(2)启动辅助类的bind()方法**
ServerBootstrap的bind()方法如下,来自其继承的抽象类AbstractBootstrap。
```csharp
//Bootstrap sub-class which allows easy bootstrap of ServerChannel
public class ServerBootstrap extends AbstractBootstrap {
...
...
}
//AbstractBootstrap is a helper class that makes it easy to bootstrap a Channel.
//It support method-chaining to provide an easy way to configure the AbstractBootstrap.
//When not used in a ServerBootstrap context, the #bind() methods are useful for connectionless transports such as datagram (UDP).
public abstract class AbstractBootstrap, C extends Channel> implements Cloneable {
...
//Create a new Channel and bind it.
public ChannelFuture bind(int inetPort) {
//首先根据端口号创建一个InetSocketAddress对象,然后调用重载方法bind()
return bind(new InetSocketAddress(inetPort));
}
//Create a new Channel and bind it.
public ChannelFuture bind(SocketAddress localAddress) {
//验证服务启动需要的必要参数
validate();
if (localAddress == null) throw new NullPointerException("localAddress");
return doBind(ObjectUtil.checkNotNull(localAddress, "localAddress"));
}
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();//1.初始化和注册Channel
final Channel channel = regFuture.channel();
...
doBind0(regFuture, channel, localAddress, promise);//2.绑定服务端端口
...
return promise;
}
...
}
```
通过传入端口号调用AbstractBootstrap的bind()方法时,首先会根据端口号创建一个InetSocketAddress对象,然后继续调用重载方法bind()。重载方法bind()会先通过validate()方法验证服务启动需要的必要参数,然后调用doBind()方法。doBind()方法中的核心方法是:initAndRegister() + doBind0()。前者用于初始化和注册Channel,后者用于绑定服务端端口。
**(3)启动辅助类的initAndRegister()方法**
```csharp
//AbstractBootstrap is a helper class that makes it easy to bootstrap a Channel.
//It support method-chaining to provide an easy way to configure the AbstractBootstrap.
public abstract class AbstractBootstrap, C extends Channel> implements Cloneable {
...
final ChannelFuture initAndRegister() {
Channel channel = null;
...
//1.创建服务端Channel
channel = channelFactory.newChannel();
//2.初始化服务端Channel
init(channel);
...
//3.注册服务端Channel,比如通过NioEventLoopGroup的register()方法进行注册
ChannelFuture regFuture = config().group().register(channel);
...
return regFuture;
}
...
}
```
**(4)服务端启动的4个核心步骤**
步骤一:创建服务端Channel
步骤二:初始化服务端Channel
步骤三:注册服务端Channel到Selector
步骤四:绑定服务端端口
**3.创建服务端Channel的源码**
**(1)Channel的概念**
**(2)Channel的创建**
**(3)ChannelFactory的创建**
**(4)通过反射创建Channel对象**
**(5)创建JDK底层NIO的Channel**
**(6)创建Channel配置类**
**(7)设置Channel类型为非阻塞**
**(8创建Channel的核心组件**
**(9)创建服务端Channel总结**
**(1)Channel的概念**
Netty官方对Channel的描述是:Channel可以理解为一个网络连接或者一个具有"读、写、连接、绑定"等IO操作能力的组件。Netty的Channel由于是在服务启动的时候创建的,可以和BIO中的ServerSocket对应,也和NIO中的ServerSocketChannel对应,所以符合上述IO组件的概念。
**(2)Channel的创建**
Channel是通过ChannelFactory的newChannel()方法创建出来的。
```csharp
//AbstractBootstrap is a helper class that makes it easy to bootstrap a Channel.
//It support method-chaining to provide an easy way to configure the AbstractBootstrap.
public abstract class AbstractBootstrap, C extends Channel> implements Cloneable {
private volatile ChannelFactory extends C> channelFactory;
...
final ChannelFuture initAndRegister() {
Channel channel = null;
...
//1.创建服务端Channel
channel = channelFactory.newChannel();
//2.初始化服务端Channel
init(channel);
...
//3.注册服务端Channel,比如通过NioEventLoopGroup的register()方法进行注册
ChannelFuture regFuture = config().group().register(channel);
...
return regFuture;
}
...
}
public interface ChannelFactory {
//Creates a new channel.
T newChannel();
}
```
**(3)ChannelFactory的创建**
ChannelFactory是通过AbstractBootstrap的channel()方法创建出来的。
用户在调用启动辅助类的channel()方法时会将NioServerSocketChannel.class,作为ReflectiveChannelFactory的构造方法的参数,从而创建出一个ReflectiveChannelFactory对象,也就是ChannelFactory对象。
```csharp
public class NettyServer {
...
public void start() throws Exception {
...
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)//监听端口的ServerSocketChannel
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer() {//处理每个客户端连接的SocketChannel
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
...
}
});
ChannelFuture channelFuture = serverBootstrap.bind(port).sync();//同步等待启动服务器监控端口
channelFuture.channel().closeFuture().sync();//同步等待关闭启动服务器的结果
...
}
}
//AbstractBootstrap is a helper class that makes it easy to bootstrap a Channel.
//It support method-chaining to provide an easy way to configure the AbstractBootstrap.
public abstract class AbstractBootstrap, C extends Channel> implements Cloneable {
private volatile ChannelFactory extends C> channelFactory;
...
//The Class which is used to create Channel instances from.
//You either use this or #channelFactory(io.netty.channel.ChannelFactory) if your Channel implementation has no no-args constructor.
public B channel(Class extends C> channelClass) {
if (channelClass == null) throw new NullPointerException("channelClass");
return channelFactory(new ReflectiveChannelFactory(channelClass));
}
@SuppressWarnings({ "unchecked", "deprecation" })
public B channelFactory(io.netty.channel.ChannelFactory extends C> channelFactory) {
return channelFactory((ChannelFactory) channelFactory);
}
public B channelFactory(ChannelFactory extends C> channelFactory) {
if (channelFactory == null) throw new NullPointerException("channelFactory");
if (this.channelFactory != null) throw new IllegalStateException("channelFactory set already");
this.channelFactory = channelFactory;
return (B) this;
}
...
}
```
**(4)通过反射创建Channel对象**
AbstractBootstrap.initAndRegister()方法中的channelFactory.newChannel()代码,最终调用的是ReflectiveChannelFactory.newChannel()方法,该方法会通过反射的方式创建出一个NioServerSocketChannel对象。
所以最终创建的服务端Channel相当于调用NioServerSocketChannel的默认构造函数来获得一个NioServerSocketChannel对象。
```csharp
//A ChannelFactory that instantiates a new Channel by invoking its default constructor reflectively.
public class ReflectiveChannelFactory implements ChannelFactory {
private final Class extends T> clazz;
public ReflectiveChannelFactory(Class extends T> clazz) {
if (clazz == null) throw new NullPointerException("clazz");
this.clazz = clazz;
}
@Override
public T newChannel() {
...
return clazz.newInstance();
}
}
```
**(5)创建JDK底层NIO的Channel**
NioServerSocketChannel的默认构造方法会调用其newSocket()方法,而newSocket()方法中会通过SelectorProvider.openServerSocketChannel()方法创建一个ServerSocketChannel对象。这个对象也就是JDK底层的Channel,即NIO的Socket。
```csharp
//A io.netty.channel.socket.ServerSocketChannel implementation which uses NIO selector based implementation to accept new connections.
public class NioServerSocketChannel extends AbstractNioMessageChannel implements io.netty.channel.socket.ServerSocketChannel {
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
private final ServerSocketChannelConfig config;
...
//Create a new instance,默认的构造方法
public NioServerSocketChannel() {
//调用newSocket()创建出一个ServerSocketChannel对象后,再调用有参构造方法
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
private static ServerSocketChannel newSocket(SelectorProvider provider) {
...
//创建一个ServerSocketChannel对象
//这个对象也就是JDK底层的Channel,即NIO的Socket
return provider.openServerSocketChannel();
}
//Create a new instance using the given ServerSocketChannel,重载的构造方法
public NioServerSocketChannel(ServerSocketChannel channel) {
//传入要关心的ACCEPT事件
super(null, channel, SelectionKey.OP_ACCEPT);
this.config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
...
}
```
**(6)创建Channel配置类**
NioServerSocketChannel的默认构造方法还会调用其重载的构造方法;在重载的构造方法里,会创建一个NioServerSocketChannelConfig对象,其顶层接口为ChannelConfig。
**(7)设置Channel类型为非阻塞**
在NioServerSocketChannel的重载构造方法里,会逐层调用父类的构造方法,比如其中就会调用AbstractNioChannel的构造方法。

在AbstractNioChannel的构造方法中,会将前面provider.openServerSocketChannel()创建的ServerSocketChannel对象,保存到AbstractNioChannel的成员变量ch中,然后再将该Channel对象设置为非阻塞模式。以及将NioServerSocketChannel重载构造方法里传入的SelectionKey.OP\_ACCEPT,设置到AbstractNioChannel的另一成员变量readInterestOp中,表示该Channel对象要关心ACCEPT事件。
注意:可以通过javaChannel()方法获取AbstractNioChannel的成员变量ch。
```csharp
//A io.netty.channel.socket.ServerSocketChannel implementation which uses NIO selector based implementation to accept new connections.
public class NioServerSocketChannel extends AbstractNioMessageChannel implements io.netty.channel.socket.ServerSocketChannel {
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
private final ServerSocketChannelConfig config;
...
//Create a new instance using the given ServerSocketChannel,重载的构造方法
public NioServerSocketChannel(ServerSocketChannel channel) {
//传入要关心的ACCEPT事件
super(null, channel, SelectionKey.OP_ACCEPT);
this.config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
...
}
//AbstractNioChannel} base class for Channels that operate on messages.
public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
...
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
}
...
}
//Abstract base class for Channel implementations which use a Selector based approach.
public abstract class AbstractNioChannel extends AbstractChannel {
private final SelectableChannel ch;//这是NIO中的Channel
protected final int readInterestOp;
...
//Create a new instance
//@param parent,the parent Channel by which this instance was created. May be null.
//@param ch,he underlying SelectableChannel on which it operates
//@param readInterestOp,the ops to set to receive data from the SelectableChannel
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent);
//NioServerSocketChannel.newSocket()方法通过JDK底层创建的Channel对象会被缓存在其父类AbstractNioChannel的变量ch中
//可以通过NioServerSocketChannel.javaChannel()方法获取其父类AbstractNioChannel的变量ch
this.ch = ch;
this.readInterestOp = readInterestOp;
...
//设置Channel对象为非阻塞模式
ch.configureBlocking(false);
...
}
protected SelectableChannel javaChannel() {
return ch;
}
...
}
```
**(8创建Channel的核心组件**
AbstractNioChannel的构造方法中还会调用其父类AbstractChannel的构造方法。在AbstractChannel的构造方法中,Netty创建了三大组件,分别赋值到其成员变量中。第一个组件是ChannelId,第二个组件是Unsafe,第三个组件是ChannelPipeline。
```csharp
//A skeletal Channel implementation.
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
private final Channel parent;
private final ChannelId id;
private final Unsafe unsafe;
private final DefaultChannelPipeline pipeline;
...
//Creates a new instance.
//@param parent,the parent of this channel. null if there's no parent.
protected AbstractChannel(Channel parent) {
this.parent = parent;
this.id = newId();
this.unsafe = newUnsafe();
this.pipeline = newChannelPipeline();
}
...
}
```
**(9)创建服务端Channel总结**
用户调用启动辅助类ServerBootstrap的bind()方法时,第一步通过反射创建服务端Channel会执行NioServerSocketChannel的默认构造方法,来创建一个NioServerSocketChannel对象,并且在创建过程中会创建Netty的一系列核心组件:如Channel、ChannelConfig、ChannelId、Unsafe、ChannelPipeline。
创建服务端Channel的关键脉络如下:
```csharp
ServerBootstrap.bind() //用户代码入口
AbstractBootstrap.initAndRegister() //初始化并注册Channel
channelFactory.newChannel() //创建服务端Channel
NioServerSocketChannel.newSocket() //通过JDK来创建JDK底层NIO的Channel
new NioServerSocketChannelConfig() //对底层NIO的Channel进行TCP参数配置
new AbstractNioChannel() //调用AbstractNioChannel的构造方法
configureBlocking(false) //设置NIO的Channel为非阻塞模式
new AbstractChannel() //调用AbstractChannel的构造方法创建组件:id、unsafe、pipeline
```
**4.初始化服务端Channel的源码**
**(1)初始化服务端Channel的时机**
**(2)初始化服务端Channel的三项工作**
**(3)初始化服务端Channel总结**
**(1)初始化服务端Channel的时机**
AbstractBootstrap的initAndRegister()方法执行channelFactory.newChannel()创建服务端Channel后,便会继续执行init(channel)对服务端Channel进行初始化。
```csharp
//AbstractBootstrap is a helper class that makes it easy to bootstrap a Channel.
//It support method-chaining to provide an easy way to configure the AbstractBootstrap.
public abstract class AbstractBootstrap, C extends Channel> implements Cloneable {
...
final ChannelFuture initAndRegister() {
Channel channel = null;
...
//1.创建服务端Channel
channel = channelFactory.newChannel();
//2.初始化服务端Channel
init(channel);
...
//3.注册服务端Channel,比如通过NioEventLoopGroup的register()方法进行注册
ChannelFuture regFuture = config().group().register(channel);
...
return regFuture;
}
//init()方法的具体逻辑会由ServerBootstrap来实现
abstract void init(Channel channel) throws Exception;
...
}
```
**(2)初始化服务端Channel的三项工作**
AbstractBootstrap的init()方法只是一个抽象方法,具体的逻辑会在ServerBootstrap类中实现。
ServerBootstrap的init()方法初始化服务端Channel主要有三项工作:
一.设置服务端Channel的Option与Attr
二.设置客户端Channel的Option与Attr
三.配置服务端启动逻辑
其中,Netty把服务端启动过程中需要执行的启动逻辑分为两部分。一部分是添加用户自定义的处理逻辑到服务端启动流程,另一部分是添加一个特殊的逻辑处理ServerBootstrapAcceptor。
ServerBootstrapAcceptor是一个接入器,用来接收新请求以及把新请求传递给某个事件循环器。
```csharp
//Bootstrap sub-class which allows easy bootstrap of ServerChannel
public class ServerBootstrap extends AbstractBootstrap {
...
@Override
void init(Channel channel) throws Exception {
//1.设置服务端Channel的Option与Attr
final Map, Object> options = options0();
synchronized (options) {
channel.config().setOptions(options);
}
final Map, Object> attrs = attrs0();
synchronized (attrs) {
for (Entry, Object> e: attrs.entrySet()) {
@SuppressWarnings("unchecked")
AttributeKey