【Netty】生命周期 详解
前言:
在我们学习 Spring
系列 时,我们发现,Spring
之所以一直立于 Java届开发基本上必选框架,其中一个 主要原因 就是:
Spring
给 使用框架的用户 留有 很多扩展点
!
在我们使用 Netty
时,会发现 Netty
给我们也留了很多 扩展点
那么,本篇博文中,本人就来讲解下 Netty
的 扩展点 —— 生命周期
首先,本人来展示下 Netty
的 生命周期
都有哪些 扩展点:
包含 扩展点:
handlerAdded
:
新建立的连接会按照初始化策略,把handler添加到该channel的pipeline里面,也就是channel.pipeline.addLast(new LifeCycleInBoundHandler)执行完成后的回调channelRegistered
:
当该连接分配到具体的worker线程后,该回调会被调用channelActive
:
channel的准备工作已经完成,所有的pipeline添加完成,并分配到具体的线上上,说明该channel准备就绪,可以使用了channelRead
:
客户端向服务端发来数据,每次都会回调此方法,表示有数据可读channelReadComplete
:
服务端每次读完一次完整的数据之后,回调该方法,表示数据读取完毕channelInactive
:
当连接断开时,该回调会被调用,说明这时候底层的TCP连接已经被断开了channelUnRegistered
:
对应channelRegistered,当连接关闭后,释放绑定的workder线程handlerRemoved
:
对应handlerAdded,将handler从该channel的pipeline移除后的回调方法
那么,这些 扩展点 的 调用顺序 是怎么样的呢?
调用顺序:
现在,本人来通过 一个小Demo 来 证明 下 上文讲解的正确性:
使用展示:
首先是 服务端:
服务端:
package edu.youzg.demo.lifecycle;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* @Author: Youzg
* @CreateTime: 2021-05-07 15:25
* @Description: 带你深究Java的本质!
*/
public class NettyServerDemo {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LifeCycleInBoundHandler());
}
});
System.out.println("Netty Server start...");
ChannelFuture channelFuture = bootstrap.bind(9000).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
static class LifeCycleInBoundHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRegistered(ChannelHandlerContext ctx)
throws Exception {
System.out.println("channelRegistered: 客户端channel注册到NioEventLoop");
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx)
throws Exception {
System.out.println("channelUnregistered: 客户端channel 取消和 NioEventLoop 的绑定");
}
@Override
public void channelActive(ChannelHandlerContext ctx)
throws Exception {
System.out.println("channelActive: channel准备就绪");
}
@Override
public void channelInactive(ChannelHandlerContext ctx)
throws Exception {
System.out.println("channelInactive: channel被关闭");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
System.out.println("channelRead: channel中有可读的数据");
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx)
throws Exception {
System.out.println("channelReadComplete: channel读数据完成");
}
@Override
public void handlerAdded(ChannelHandlerContext ctx)
throws Exception {
System.out.println("handlerAdded: handler被添加到channel的pipeline");
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx)
throws Exception {
System.out.println("handlerRemoved: handler从channel的pipeline中移除");
}
}
}
接下来是 客户端:
客户端:
package edu.youzg.demo.lifecycle;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.nio.charset.StandardCharsets;
/**
* @Author: Youzg
* @CreateTime: 2021-05-07 15:25
* @Description: 带你深究Java的本质!
*/
public class NettyClientDemo {
public static void main(String[] args) {
NioEventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ClientHandler());
}
});
System.out.println("Netty Client start...");
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9000).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
static class ClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.copiedBuffer("Youzg is a good man!".getBytes(StandardCharsets.UTF_8)));
}
}
}
最后,本人来展示下 运行结果:
运行结果:
我们可以看到:
生命周期Handler 的 调用顺序,和本人上文所讲一致!
那么,至此,Netty
的 生命周期
,就讲解完毕了!
在之后的博文中,本人也会通过讲解 源码,来讲解下 Netty
内部的 实现逻辑