netty官网: https://netty.io/
原生NIO存在的问题
- NIO 的类库和 API 繁杂,使用麻烦:需要熟练掌握 Selector、ServerSocketChannel、SocketChannel、ByteBuffer等。
- 需要具备其他的额外技能:要熟悉 Java 多线程编程,因为 NIO 编程涉及到 Reactor 模式,你必须对多线程和网络编程非常熟悉,才能编写出高质量的 NIO 程序。
- 开发工作量和难度都非常大:例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常流的处理等等。
- JDK NIO 的 Bug:例如臭名昭著的 Epoll Bug,它会导致 Selector 空轮询,最终导致 CPU 100%。直到 JDK 1.7 版本该问题仍旧存在,没有被根本解决。
Netty特点
- Netty 是由 JBOSS 提供的一个 Java 开源框架,现为 Github上的独立项目。
- Netty 是一个异步的、基于事件驱动的网络应用框架,用以快速开发高性能、高可靠性的网络 IO 程序。
- Netty主要针对在TCP协议下,面向Clients端的高并发应用,或者Peer-to-Peer场景下的大量数据持续传输的应用。
- Netty本质是一个NIO框架,适用于服务器通讯相关的多种应用场景
Netty线程模型
目前存在的线程模型有:
+ 传统阻塞 I/O 服务模型 (即一个线程处理一个IO)
+ Reactor 模式
Reactor模式又称反应器模式、分发者模式(Dispatcher) 、通知者模式(notifier)
Reactor 在一个单独的线程中运行,负责监听和分发事件,分发给适当的处理程序来对 IO 事件做出反应。 它就像公司的电话接线员,它接听来自客户的电话并将线路转移到适当的联系人。
根据 Reactor 的数量和处理资源池线程的数量不同,有 3 种典型的实现
+ 单 Reactor 单线程
+ 单 Reactor 多线程
+ 主从 Reactor 多线程
mainReactor负责监听server socket,accept新连接,并将建立的socket分派给subReactor。subReactor负责多路分离已连接的socket,读写网 络数据,对业务处理功能,其扔给worker线程池完成。通常,subReactor个数上可与CPU个数等同
Netty 主要基于主从 Reactor 多线程模型,做了一定的改进,其中主从 Reactor 多线程模型有多个 Reactor
netty架构
- Netty抽象出两组线程池
BossGroup
专门负责接收客户端的连接,WorkerGroup
专门负责网络的读写。 - BossGroup 和 WorkerGroup 类型都是 NioEventLoopGroup
- NioEventLoopGroup 相当于一个事件循环组, 这个组中含有多个事件循环 ,每一个事件循环是 NioEventLoop
- NioEventLoop 表示一个不断循环的执行处理任务的线程, 每个NioEventLoop 都有一个selector , 用于监听绑定在其上的socket的网络通讯
- NioEventLoopGroup 可以有多个线程, 即可以含有多个NioEventLoop
- 每个Boss NioEventLoop 循环执行的步骤有3步
select
: 轮询accept 事件processSelectedKeys
: 处理accept 事件 , 与client建立连接 , 生成NioScocketChannel , 并将其注册到某个worker NIOEventLoop 上的 selectorrunAllTasks
: 处理任务队列的任务
- 每个 Worker NIOEventLoop 循环执行的步骤
select
: 轮询read, write事件processSelectedKeys
: 处理i/o事件, 即read , write 事件,在对应NioSocketChannel处理runAllTasks
: 处理任务队列的任务,即 runAllTasks
- 每个Worker NIOEventLoop 处理业务时,会使用pipeline(管道), pipeline 中包含了 channel , 即通过pipeline 可以获取到对应通道, 管道中维护了很多的处理器
原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/netty%e6%a6%82%e8%bf%b0%ef%bc%88%e7%ba%bf%e7%a8%8b%e6%a8%a1%e5%9e%8b%ef%bc%89/