目录
🍍上面NettyServerHandler中的方法是由Netty的事件循环(EventLoop)触发调用的。
🍍Netty的事件循环(EventLoop)是通过NIO Selector实现的。
🍍Netty介绍:
- Netty是一个基于Java NIO的网络通信框架,用于快速开发高性能、高可靠性的网络应用程序。它提供了一组易于使用的API,可以轻松地实现各种网络协议和应用程序,如HTTP、WebSocket、TCP、UDP等。Netty的主要特点包括:
-
高性能:Netty使用异步、事件驱动的模型,可以处理大量的并发连接和请求。
-
可扩展性:Netty的设计模式和组件化架构使得它非常易于扩展和定制。
-
易于使用:Netty提供了简单易用的API和文档,使得开发人员可以快速上手。
-
可靠性:Netty提供了丰富的错误处理机制和异常处理机制,可以保证应用程序的稳定性和可靠性。
-
安全性:Netty提供了SSL/TLS支持,可以保证网络通信的安全性。
🍍基于Netty的异步、事件驱动的模型
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;
public class NettyServer {
private int port;
public NettyServer(int port) {
this.port = port;
}
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new HttpServerCodec());
ch.pipeline().addLast(new HttpObjectAggregator(65536));
ch.pipeline().addLast(new ChunkedWriteHandler());
ch.pipeline().addLast(new NettyServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port = 8080;
new NettyServer(port).run();
}
}
🍍 Netty的高级特性的代码实现逻辑的解释:
HttpServerCodec:用于处理HTTP请求和响应的编解码器。
在NettyServer类的childHandler()方法中,我们添加了一个HttpServerCodec对象,用于将HTTP请求和响应的字节流转换为HTTP消息对象。HttpServerCodec实际上是一个编解码器,它将HTTP请求和响应的字节流转换为HTTP消息对象,然后将HTTP消息对象转换为字节流发送给客户端。
HttpObjectAggregator:用于将HTTP请求和响应的多个部分合并成一个完整的消息。
在NettyServer类的childHandler()方法中,我们添加了一个HttpObjectAggregator对象,用于将HTTP请求和响应的多个部分合并成一个完整的消息。HttpObjectAggregator实际上是一个聚合器,它将HTTP请求和响应的多个部分合并成一个完整的消息,然后将完整的消息传递给下一个处理器进行处理。
ChunkedWriteHandler:用于处理大文件或大数据流的传输。
在NettyServer类的childHandler()方法中,我们添加了一个ChunkedWriteHandler对象,用于处理大文件或大数据流的传输。ChunkedWriteHandler实际上是一个处理器,它可以将大文件或大数据流分成多个块进行传输,从而避免一次性将整个文件或数据流加载到内存中。
PooledByteBufAllocator:用于内存池分配,可以提高内存使用效率。
在NettyServer类的childOption()方法中,我们设置了一个PooledByteBufAllocator对象,用于内存池分配。PooledByteBufAllocator实际上是一个内存池分配器,它可以提高内存使用效率,避免频繁地创建和销毁ByteBuf对象,从而提高性能和可靠性。
new NettyServerHandler()
表示创建一个NettyServerHandler
类的实例,NettyServerHandler
类是一个自定义的业务逻辑处理器,实现了ChannelInboundHandler
接口。
在Netty中,ChannelInboundHandler
用于处理入站事件(例如接收到的数据),ChannelOutboundHandler
用于处理出站事件(例如要发送的数据)。业务逻辑处理器通常实现ChannelInboundHandler
接口,用于处理从客户端接收到的数据或者连接事件等。
在通道处理链(ChannelPipeline
)中不同的组件将会负责不同的任务,例如读取数据、解码数据、编码数据、协议处理、业务处理等。业务处理器是通道处理链中的最后一步,用于处理业务逻辑。它将在之前的组件将接收到的数据解码,进行协议处理后,将处理结果交给业务处理器进行进一步的处理。
在添加业务处理器时,可以通过ch.pipeline().addLast(new NettyServerHandler())
将其添加到通道处理链中。这样,在服务端接收到客户端的数据时,经过之前的组件处理后,数据将交给ServerHandler
进行业务处理。
🍍NettyServerHandler 业务处理简单实现:
public class NettyServerHandlerextends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 处理读取到的数据
ByteBuf buf = (ByteBuf) msg;
String data = buf.toString(CharsetUtil.UTF_8);
System.out.println("Received data: " + data);
// 回写响应数据
String response = "Hello, client!";
ByteBuf respBuf = Unpooled.copiedBuffer(response, CharsetUtil.UTF_8);
ctx.write(respBuf);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// 刷新缓冲区,将响应数据发送给客户端
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// 处理异常
cause.printStackTrace();
ctx.close();
}
}
🍍依赖:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.63.Final</version>
</dependency>
🍍Netty API:
Channel:表示一个网络连接,可以用于读取和写入数据。
ChannelHandler:表示一个处理器,用于处理网络事件和数据。
EventLoop:表示一个事件循环,用于处理事件和任务。
Bootstrap:用于启动客户端连接。
ServerBootstrap:用于启动服务器端连接。
ByteBuf:表示一个字节缓冲区,用于读取和写入数据。
Codec:表示一个编解码器,用于将数据转换为字节流或消息对象。
Future:表示一个异步操作的结果,可以用于获取操作结果或添加回调函数。
Promise:表示一个异步操作的结果,可以用于设置操作结果或添加回调函数。
ChannelPipeline:表示一个处理器链,用于将多个处理器组合成一个处理器。
ChannelHandlerContext:表示一个处理器上下文,用于获取当前处理器的信息和操作。
ChannelFuture:表示一个异步操作的结果,可以用于获取操作结果或添加回调函数。
ChannelFutureListener:表示一个异步操作的回调函数,用于处理操作结果。
ChannelOption:表示一个通道选项,用于设置通道的参数。
ChannelConfig:表示一个通道配置,用于设置通道的参数。
ChannelInboundHandlerAdapter:表示一个入站处理器适配器,用于处理入站事件和数据。
ChannelOutboundHandlerAdapter:表示一个出站处理器适配器,用于处理出站事件和数据。
ChannelDuplexHandler:表示一个双向处理器,用于处理入站和出站事件和数据。
ChannelInitializer:表示一个通道初始化器,用于初始化通道的处理器链。
ChannelPromise:表示一个异步操作的结果,可以用于设置操作结果或添加回调函数。
NioEventLoopGroup:表示一个NIO事件循环组,用于处理NIO事件。
EpollEventLoopGroup:表示一个Epoll事件循环组,用于处理Epoll事件。
DefaultEventExecutorGroup:表示一个默认的事件执行器组,用于执行事件处理器。
DefaultChannelGroup:表示一个默认的通道组,用于管理通道。
DefaultChannelHandlerContext:表示一个默认的通道处理器上下文,用于获取当前处理器的信息和操作。
DefaultChannelPipeline:表示一个默认的通道处理器链,用于将多个处理器组合成一个处理器。
EmbeddedChannel:表示一个嵌入式通道,用于测试通道处理器。
AttributeKey:表示一个属性键,用于设置通道的属性。
Attribute:表示一个通道属性,用于设置和获取通道的属性。
SslContext:表示一个SSL上下文,用于加密和解密数据。
🍍流程讲解:
🍍上面NettyServerHandler
中的方法是由Netty的事件循环(EventLoop)触发调用的。
在Netty中,事件循环是一个线程,它负责监听所有的I/O事件,包括连接事件、读写事件、异常事件等等。当有事件发生时,事件循环会将该事件封装成一个Netty的事件对象,并将该事件分配给事件循环中的一个线程去处理。
具体来说,在Netty服务端接收到客户端发送的消息时,Netty会将这个事件封装成一个ChannelReadEvent
事件对象,然后将该事件对象分配到事件循环中的一个线程去处理。在事件循环中,事件对象会被传递给处理链(Pipeline),然后经过各个组件的处理,直到到达业务处理器(就是我们定义的ServerHandler)。
当业务处理器接收到事件对象时,业务处理器会根据事件对象的类型以及业务逻辑的需要,调用相应的方法进行处理。例如,在NettyServerHandler
中,我们重写了channelRead
方法,用于处理客户端发送的消息。当一个ChannelReadEvent
事件对象传递到ServerHandler时,Netty会自动调用channelRead
方法,并将接收到的消息作为参数传递给该方法,业务处理器可以在该方法中对消息进行处理,然后将处理结果发送给客户端。
综上所述,ServerHandler中的方法是由Netty的事件循环触发调用的,当服务端接收到客户端发送的消息时,Netty会将该事件封装成一个事件对象,并将该事件对象分配到事件循环中的一个线程去处理,事件对象会经过处理链中的各个组件进行加工处理,最终到达业务处理器中,业务处理器根据消息的内容进行处理,并将处理结果返回给客户端。
🍍Netty的事件循环(EventLoop)是通过NIO Selector实现的。
在Java NIO中,Selector是一个多路复用器,它可以同时监控多个通道的IO事件。当一个通道发生IO事件时,Selector会将该事件加入到事件集合中,并通知事件循环处理器处理这些事件。
在Netty中,事件循环是一个线程,它负责处理事件和数据,并将它们传递给事件处理器进行处理。事件循环会不断地从事件队列中取出事件,并将事件传递给事件处理器进行处理。
Netty的事件循环模型是基于NIO Selector实现的。当Netty启动一个服务端或客户端时,它会创建一个或多个事件循环组(EventLoopGroup),每个事件循环组包含一个或多个事件循环(EventLoop)。
每个事件循环都会创建一个NIO Selector,并在事件循环线程中不断地轮询Selector,以便处理通道的IO事件。当一个通道发生IO事件时,Selector会将该事件加入到事件集合中,并通知事件循环处理器处理这些事件。
事件循环会将事件封装成事件对象,并将事件对象放入事件队列中。事件处理器会从事件队列中取出事件,并进行处理。当事件处理器处理完一个事件后,它会将处理结果返回给事件循环,事件循环会将处理结果发送给客户端或服务端。
因此,Netty的事件循环(EventLoop)是通过NIO Selector实现的。事件循环会不断地轮询Selector,以便处理通道的IO事件,并将事件封装成事件对象放入事件队列中。事件处理器会从事件队列中取出事件,并进行处理。