ServerBootstrap运行过程
服务端从启动到新连接的改变过程
ServerBootstrap初始化过程
(1)EventLoopGroup:无论是服务端还是客户端,都必须指定EventLoopGroup。在上面的代码中,指定了NioEventLoopGroup,表示一个NIO的EventLoopGroup,不过服务端需要指定两个EventLoopGroup,一个是bossGroup,用于处理客户端的连接请求;另一个是workerGroup,用于处理与各个客户端连接的I/O操作。
(2)指定Channel的类型。这里是服务端,所以使用了NioServerSocketChannel。
(3)配置自定义的业务处理器Handler。
NioServerSocketChannel
public NioServerSocketChannel(ServerSocketChannel channel) {
//设置SelectionKey.OP_ACCEPT,也就是通知Selector我们对客户端的连接请求感兴趣
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
(1)调用NioServerSocketChannel.newSocket(DEFAULT_SELECTOR_PROVIDER)方法创建一个新的Java NIO原生的ServerSocketChannel对象。
(2)实例化AbstractChannel对象并给属性赋值,具体赋值的属性如下。
● parent:设置为默认值null。
● unsafe:通过调用newUnsafe()方法,实例化一个Unsafe对象,其类型是AbstractNioMessageChannel.AbstractNioUnsafe内部类。
● pipeline:赋值的是DefaultChannelPipeline的实例。
(3)实例化AbstractNioChannel对象并给属性赋值,具体赋值的属性如下。
● ch:被赋值为Java NIO原生的ServerSocketChannel对象,通过调用NioServerSocketChannel的newSocket()方法获取。● readInterestOp:被赋值为默认值SelectionKey.OP_ACCEPT。
● Ch:被设置为非阻塞,也就是调用ch.configureBlocking(false)方法。
(4)给NioServerSocketChannel对象的config属性赋值为new NioServerSocketChannelConfig(this,javaChannel().socket())。
EventLoop启动完整过程
ServerBootstrapAcceptor
ServerBootstrap#init()
ServerBootstrap#init(){
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = handler();
if (handler != null) {
pipeline.addLast(handler);
}
//读取客户端连接
pipeline.addLast(new ServerBootstrapAcceptor(
currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter {
public void channelRead(ChannelHandlerContext ctx, Object msg) {
final Channel child = (Channel) msg;
child.pipeline().addLast(childHandler);
for (Entry<ChannelOption<?>, Object> e: childOptions) {
......
try {
//childGroup的register()方法就是将workerGroup中的某个EventLoop和NioSocketChannel进行关联
childGroup.register(child).addListener(new ChannelFutureListener() {
......
});
} catch (Throwable t) {
forceClose(child, t);
}
}
}
bossGroup与workerGroup
bossGroup只用于服务端的accept,也就是用于处理客户端新连接接入的请求。我们可以把Netty比作一个餐馆,bossGroup就像一个大堂经理,当客户来到餐馆吃饭时,大堂经理就会引导顾客就座,为顾客端茶送水等。而workerGroup就是实际干活的厨师,它们负责客户端连接通道的I/O操作:当大堂经理接待顾客后,顾客可以稍做休息,而此时后厨里的厨师们(workerGroup)就开始忙碌地准备饭菜了
Pipeline设计原理*
在初始化Bootstrap时通过handler()方法设置的ChannelInitializer实例,因此这里就将ChannelInitializer插到了Pipeline的末端
自定义ChannelHandler的添加过程
Pipeline的事件传播机制
Inbound事件和Outbound事件的流向是不一样的,
Inbound事件的流向是从下至上的,是通过调用相应的ChannelHandlerContext.fireIN_EVT()方法来传递的.
Outbound恰好相反,是从上到下,是通过调用ChannelHandlerContext.OUT_EVT()方法来传递的
例如:ChannelHandlerContext的fireChannelRegistered()调用会发送一个ChannelRegistered的Inbound给下一个ChannelHandlerContext,而ChannelHandlerContext的bind()方法调用时会发送一个bind的Outbound事件给下一个ChannelHandlerContext。
Outbound事件传播方式
Inbound事件传播方式
Inbound类似于事件回调(响应请求的事件),而Outbound类似于主动触发(发起请求的事件)
ChannelHandlerContext*
在ServerBootstrapAcceptor章节出现
每个ChannelHandler被添加到ChannelPipeline后,都会创建一个ChannelHandlerContext,并与ChannelHandler关联绑定。ChannelHandlerContext允许ChannelHandler与其他的ChannelHandler进行交互。ChannelHandlerContext不会改变添加到其中的ChannelHandler,因此它是安全的。ChannelHandlerContext、ChannelHandler和ChannelPipeline的关系如下图所示
Channel的生命周期
一个Channel正常的生命周期如下图所示。随着状态发生变化产生相应的事件。这些事件被转发到ChannelPipeline中的ChannelHandler来触发相应的操作。
异步结果Future&异步执行Promise
通过 Future 和 ChannelFutures,他们可以注册一个监听,当操作执行成功或失败时监听会自动触发注册的监听事件。