目录
Netty 的核心组件
Netty由三层结构构成,1.网络通信层2事件调度层3.服务编排层。
在网络通信层有三个核心组件Bootstrap 、ServerBootstrap和Channel,Bootstrap负责客户端启动并去连接远程的Netty Server,ServerBootstrap是负责服务端的监听,监听指定的一个端口,Channel是负责网络通信的一个载体,事件调度器。
事件调度器有两个核心角色,EventLoopGroup和EventLoop,EventLoopGroup本质上是一个线程池,主要去负责接收IO请求并分配线程去执行处理请求,EventLoop相对于线程池里的一个具体线程。
在服务编排层有三个核心组件,ChannelHandler(消息处理器) 、 ChannelPipeline(ChannelHandler 对象链表)和ChannelHandlerContext。ChannelPipeline负责处理多个ChannelHandler,它会把多个ChannelHandler构成一个链去形成这样一个Pipeline,ChannelHandler主要是针对IO数据的一个处理器,数据接收后通过指定的一个lHandler进行处理,ChannelHandlerContext是用来保存ChannelHandler的上下文信息的。
Bytebuf(字节容器)
网络通信最终都是通过字节流进行传输的。 ByteBuf 就是 Netty 提供的一个字节容器,其内部是一个字节数组。 当我们通过 Netty 传输数据的时候,就是通过 ByteBuf 进行的。
我们可以将 ByteBuf 看作是 Netty 对 Java NIO 提供的ByteBuffer 字节容器的封装和抽象。为什么不直接使用 Java NIO 提供的 ByteBuffer 呢?因为 ByteBuffer 这个类使用起来过于复杂和繁琐。
Bootstrap 和 ServerBootstrap(启动引导类)
Bootstrap 是客户端的启动引导类/辅助类
EventLoopGroup group = new NioEventLoopGroup();
try {
//创建客户端启动引导/辅助类:Bootstrap
Bootstrap b = new Bootstrap();
//指定线程模型
b.group(group).
......
// 尝试建立连接
ChannelFuture f = b.connect(host, port).sync();
f.channel().closeFuture().sync();
} finally {
// 优雅关闭相关线程组资源
group.shutdownGracefully();
}
ServerBootstrap 是服务端的启动引导类/辅助类
// 1.bossGroup 用于接收连接,workerGroup 用于具体的处理
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//2.创建服务端启动引导/辅助类:ServerBootstrap
ServerBootstrap b = new ServerBootstrap();
//3.给引导类配置两大线程组,确定了线程模型
b.group(bossGroup, workerGroup).
......
// 6.绑定端口
ChannelFuture f = b.bind(port).sync();
// 等待连接关闭
f.channel().closeFuture().sync();
} finally {
//7.优雅关闭相关线程组资源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
- Bootstrap 通常使用 connect() 方法连接到远程的主机和端口,作为一个 Netty TCP 协议通信中的客户端。另外,Bootstrap 也可以通过 bind() 方法绑定本地的一个端口,作为 UDP 协议通信中的一端。
- ServerBootstrap通常使用 bind() 方法绑定本地的端口上,然后等待客户端的连接。
- Bootstrap 只需要配置一个线程组— EventLoopGroup ,而 ServerBootstrap需要配置两个线程组— EventLoopGroup ,一个用于接收连接,一个用于具体的 IO 处理。
Channel(网络操作抽象类)
Channel 接口是 Netty 对网络操作抽象类。通过 Channel 我们可以进行 I/O 操作。
一旦客户端成功连接服务端,就会新建一个 Channel 同该用户端进行绑定。
// 通过 Bootstrap 的 connect 方法连接到服务端
public Channel doConnect(InetSocketAddress inetSocketAddress) {
CompletableFuture<Channel> completableFuture = new CompletableFuture<>();
bootstrap.connect(inetSocketAddress).addListener((ChannelFutureListener)future -> {
if (future.isSuccess()) {
completableFuture.complete(future.channel());
} else {
throw new IllegalStateException(