概念
Netty是一个异步的、事件驱动的网络应用框架,用于快速的开发高性能的服务端和客户端。简化了NIO的开发流程。
原生NIO存在的问题
- NIO 的类库和 API 繁杂,使用麻烦:需要熟练掌握 Selector、ServerSocketChannel、SocketChannel、ByteBuffer 等。
- 要具备其他的额外技能:要熟悉 Java 多线程编程,因为 NIO 编程涉及到 Reactor 模式,你必须对多线程和网络编程非常熟悉,才能编写出高质量的 NIO 程序。
- 开发工作量和难度都非常大:例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常流的处理等等。
- JDK NIO 的 Bug:例如臭名昭著的 Epoll Bug,它会导致 Selector 空轮询,最终导致 CPU 100%。直到 JDK 1.7 版本该问题仍旧存在,没有被根本解决。
Netty优点
Netty 对 JDK 自带的 NIO 的 API 进行了封装,解决了以下问题:
- 设计优雅:适用于各种传输类型的统一 API 阻塞和非阻塞 Socket;基于灵活且可扩展的事件模型,可以清晰地分离关注点;高度可定制的线程模型 - 单线程,一个或多个线程池;
- 使用方便:详细记录的 Javadoc,用户指南和示例;没有其他依赖项,JDK 5(Netty 3.x)或 6(Netty 4.x)就足够了;
- 高性能、吞吐量更高:延迟更低;减少资源消耗;最小化不必要的内存复制;
- 安全:完整的 SSL/TLS 和 StartTLS 支持;
- 社区活跃、不断更新:社区活跃,版本迭代周期短,发现的 Bug 可以被及时修复,同时,更多的新功能会被加入;
Netty版本
- netty版本分为 netty3.x 和 netty4.x、netty5.x;(3太老了,不建议使用)
- 因为Netty5出现重大bug,已经被官网废弃了,目前推荐使用的是Netty4.x的稳定版本;(Netty4.1.x)
- 目前在官网可下载的版本 netty3.x netty4.0.x 和 netty4.1;
- netty 下载地址: https://bintray.com/netty/downloads/netty/
线程模型基本介绍
- 传统阻塞 I/O 服务模型
- Reactor 模型,根据 Reactor 的数量和处理资源池线程的数量不同,有 3 种典型的实现:
- 单 Reactor 单线程;
- 单 Reactor 多线程;
- 主从 Reactor 多线程;
- Netty 线程模式(Netty 主要基于主从 Reactor 多线程模型做了一定的改进,其中主从 Reactor 多线程模型有多个 Reactor)
传统 I/O 服务模型
略,不支持高并发,阻塞式线程造成资源浪费
Reactor 模型
-
叫法:1. 反应器模式;2. 分发者模式(Dispatcher);3. 通知者模式(Notifier);
-
特点:
-
基于 I/O 复用模型:多个连接共用一个阻塞对象,应用程序只需要在一个阻塞对象等待,无需阻塞等待所有连接。当某个连接有新的数据可以处理时,操作系统通知应用程序,线程从阻塞状态返回,开始进行业务处理;
-
基于线程池复用线程资源:不必再为每个连接创建线程,将连接完成后的业务处理任务分配给线程进行处理,一个线程可以处理多个连接的业务
-
理解:类似于写阻塞式连接+多线程的模型:一个线程处理监听事件,而每次监听到的连接为其开出两个线程进行数据收发,但如果多个连接进来后可能会造成错误,后续处理业务逻辑的线程的资源回收也是个问题。而这边的模型的监听线程则开一个ServiceHandler单独处理,有线程过来则通知到线程池中,也就是两个地方都有复用的地方;上述的阻塞式连接+多线程的模型如果把多线程池化可以得到一定优化。这个模型有点类似于单Reactor 多线程,但注意还是同步阻塞的,因为监听线程一致处在监听的状态,而不是事件驱动、轮询的模式
-
核心组成
- Reactor,负责分发事件
- Handler,负责真正的逻辑处理
模型图:
单 Reactor 单线程
类比之前的群聊系统
模型图:
缺点:高并发场景不适用,比如已经有新的请求给 Reactor 了,但可能还在 Handler 中处理 read 或者其他情况,造成阻塞