Netty架构原理深度解析,必学框架!

本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件、整体架构,知其然且知其所以然,希望给大家在实际开发实践、学习开源项目方面提供参考 。

Netty架构原理深度解析,必学框架!

文章插图
 
Netty 是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端 。
JDK 原生 NIO 程序的问题
JDK 原生也有一套网络应用程序 API,但是存在一系列问题,主要如下:
NIO 的类库和 API 繁杂,使用麻烦 。你需要熟练掌握 Selector、ServerSocketChannel、SocketChannel、ByteBuffer 等 。
需要具备其他的额外技能做铺垫 。例如熟悉 JAVA 多线程编程,因为 NIO 编程涉及到 Reactor 模式,你必须对多线程和网路编程非常熟悉,才能编写出高质量的 NIO 程序 。
可靠性能力补齐,开发工作量和难度都非常大 。例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等等 。NIO 编程的特点是功能开发相对容易,但是可靠性能力补齐工作量和难度都非常大 。
JDK NIO 的 Bug 。例如臭名昭著的 Epoll Bug,它会导致 Selector 空轮询,最终导致 CPU 100% 。官方声称在 JDK 1.6 版本的 update 18 修复了该问题,但是直到 JDK 1.7 版本该问题仍旧存在,只不过该 Bug 发生概率降低了一些而已,它并没有被根本解决 。
Netty 的特点
Netty 对 JDK 自带的 NIO 的 API 进行封装,解决上述问题,主要特点有:
设计优雅,适用于各种传输类型的统一 API 阻塞和非阻塞 Socket;基于灵活且可扩展的事件模型,可以清晰地分离关注点;高度可定制的线程模型 - 单线程,一个或多个线程池;真正的无连接数据报套接字支持(自 3.1 起) 。
使用方便,详细记录的 Javadoc,用户指南和示例;没有其他依赖项,JDK 5(Netty 3.x)或 6(Netty 4.x)就足够了 。
高性能,吞吐量更高,延迟更低;减少资源消耗;最小化不必要的内存复制 。
安全,完整的 SSL/TLS 和 StartTLS 支持 。
社区活跃,不断更新,社区活跃,版本迭代周期短,发现的 Bug 可以被及时修复,同时,更多的新功能会被加入 。
Netty 常见使用场景
Netty 常见的使用场景如下:
互联网行业 。在分布式系统中,各个节点之间需要远程服务调用,高性能的 RPC 框架必不可少,Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些 RPC 框架使用 。典型的应用有:阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用 Netty 作为基础通信组件,用于实现各进程节点之间的内部通信 。
游戏行业 。无论是手游服务端还是大型的网络游戏,Java 语言得到了越来越广泛的应用 。Netty 作为高性能的基础通信组件,它本身提供了 TCP/UDP 和 HTTP 协议栈 。非常方便定制和开发私有协议栈,账号登录服务器,地图服务器之间可以方便的通过 Netty 进行高性能的通信 。
大数据领域 。经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨界点通信,它的 Netty Service 基于 Netty 框架二次封装实现 。
有兴趣的读者可以了解一下目前有哪些开源项目使用了 Netty:Related Projects 。
Netty 高性能设计
Netty 作为异步事件驱动的网络,高性能之处主要来自于其 I/O 模型和线程处理模型,前者决定如何收发数据,后者决定如何处理数据 。
I/O 模型
用什么样的通道将数据发送给对方,BIO、NIO 或者 AIO,I/O 模型在很大程度上决定了框架的性能 。
阻塞 I/O
传统阻塞型 I/O(BIO)可以用下图表示:
Netty架构原理深度解析,必学框架!

文章插图
 
Blocking I/O
特点如下:
每个请求都需要独立的线程完成数据 Read,业务处理,数据 Write 的完整操作问题 。
当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大 。
连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 Read 操作上,造成线程资源浪费 。
I/O 复用模型
Netty架构原理深度解析,必学框架!

文章插图
 
在 I/O 复用模型中,会用到 Select,这个函数也会使进程阻塞,但是和阻塞 I/O 所不同的是这两个函数可以同时阻塞多个 I/O 操作 。
而且可以同时对多个读操作,多个写操作的 I/O 函数进行检测,直到有数据可读或可写时,才真正调用 I/O 操作函数 。


推荐阅读