同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。
IO是多线程的,阻塞的。NIO,是同步的非阻塞IO。
IO面向Stream(流),而NIO面向Buffer(缓冲区)。
IO是多个线程的,不存在Selector。而Java NIO的Selector(选择器)允许一个单独的线程来监视多个Channel(输入通道)。
NIO,同步非阻塞,IO多路复用。
NIO包括Channel、Select、Buffer这些。
Selector允许单线程处理多个 Channel。
Q:Netty 高性能表现在哪些方面?
主从Reactor多线程模型有多个Reactor:MainReactor和SubReactor:
详情见: https://blog.csdn.net/sinat_32502451/article/details/133934402
基本过程如下:
1 初始化创建2个NioEventLoopGroup,其中boosGroup用于Accetpt连接建立事件并分发请求, workerGroup用于处理I/O读写事件和业务逻辑。
2 基于ServerBootstrap(服务端启动引导类),配置EventLoopGroup、Channel类型,连接参数、配置入站、出站事件handler。
3 绑定端口,开始工作。
单线程模型
多线程模型
主从多线程模型:从一个 主线程 NIO 线程池中选择一个线程作为 Acceptor 线程,绑定监听端口,接收客户端连接的连接,其他线程负责后续的接入认证等工作。连接建立完成后,Sub NIO 线程池负责具体处理 I/O 读写。
select、poll和epoll都是用于实现 I/O 多路复用的方式,可以在同一时间内监听多个文件描述符的就绪状态。
select 使用位图来表示文件描述符的状态。调用 select 时,内核需要遍历整个位图,检查每个文件描述符是否就绪。这种轮询的方式在连接数量很少时还是很有效的,但当连接数量增多时,性能会下降。 select 文件描述符个数只能支持 2048 个,不过 select 的跨平台性比较好,几乎所有的平台都可以支持。
poll 使用链表结构来表示文件描述符的状态,没有最大连接数的限制。和 select 函数一样,poll 返回后,需要轮询来获取就绪的描述符,因此随着监视的描述符数量的增长,其效率也会线性下降。
epoll 是 Linux 特有的一种方式,它使用了事件驱动的模型,没有最大连接数的限制。它将文件描述符添加到 epoll 的事件集合中,等待事件的发生。与 select 和 poll 不同的是,epoll 不需要轮询,它使用回调的方式,只关注真正发生事件的文件描述符。这使得epoll在大规模高并发连接下具有卓越的性能。
应用场景上,select和poll适用于连接数量较少的场景,而epoll则适用于需要处理大规模并发连接且性能要求较高的场景。
Netty 默认是 CPU 处理器数的两倍,bind 完之后启动。
拆包:一个完整的应用包可能会被 TCP 拆分成多个包进行发送。
粘包:也可能把小应用包的封装成一个大的 TCP数据包发送。
应用程序写入的字节大小大于套接字发送缓冲区的大小,会发生拆包现象,
而应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包现象。
解决方法 :
Netty中提供了多个 Decoder 解析类 用于解决上述问题:
FixedLengthFrameDecoder 、LengthFieldBasedFrameDecoder ,固定长度是消息头指定消息长度的一种形式,进行粘包拆包处理的。
LineBasedFrameDecoder 、DelimiterBasedFrameDecoder ,换行是于指定消息边界方式的一种形式,进行消息粘包拆包处理的。
Netty 有两种发送消息的方式:
直接写入 Channel 中,消息从 ChannelPipeline 当中尾部开始移动;
写入和 ChannelHandler 绑定的 ChannelHandlerContext 中,消息从 ChannelPipeline 中的下一个 ChannelHandler 中移动。
Netty 的零拷贝主要包含三个方面:
https://blog.csdn.net/crazymakercircle/article/details/124588880