持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情
介绍
Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。
它提供了对TCP、UDP、文件传输支持,其所有的IO操作都是异步的。
Netty的优点
我们为什么要选Netty?它有说明优点? 优点如下:
- 高性能,在主流的NIO框架中,Netty性能最优。
- API简单,学习成本低。
- 可扩展性、功能强大。
有很多优秀的项目都在使用Netty,如Dubbo、Elasticsearch、Hadoop的RPC框架。
说了这么多,有jym会它到底牛掰在哪里?高性能在哪?
好!这里我就来说一说它牛在哪。
Netty的高性能
从几个方面进行分析:
1. 传输,底层的IO框架:
Netty采用了NIO的多路复用技术。Netty的IO线程 NioEventLoop 由于聚合了多路复用器 Selector,可以同时并发处理成百上千个客户端Channel,Netty的IO操作都是非阻塞的,避免了IO阻塞导致线程挂起。
IO多路复用的最大优势就是线条开销小,不需要额外创建进程和线程及维护这些进程、线程,减少了系统工作量,节省系统资源。
2. 线程模型:
Reactor线程模型是对于传统的I/O线程模型的一种优化。
常用的Reactor线程模型有三种,Reactor单线程模型, Reactor多线程模型, 主从Reactor多线程模型。
Reactor单线程模型
是指所有的IO操作都在同一个线程上完成。
其职责如下:
即可以作为客户端和服务端,担任相应的职责,以及读取/发送通信端的请求及响应。
缺点:只有一个线程处理任务,高并发下容易阻塞,且不可靠。
Reactor多线程模型
Reactor多线程模型与单线程模型最大的区别就是有一组NIO线程处理IO操作。有一个专门的Acceptor线程用于监听服务端,及接收客户端的TCP连接请求,IO操作则由线程池去处理。
缺点:虽然其线程池处理IO操作,充分发挥了多核CPU的能力,但是仅仅使用一个NIO线程去监听服务端和处理所有的连接请求,在高并发下仍然会存在性能问题。
主从Reactor多线程模型
服务端用于接收客户端连接的不再是个1个单独的NIO线程,而是一个独立的NIO线程池。
Acceptor接收到客户端TCP连接请求处理完成后(可能包含接入认证等),将新创建的SocketChannel注册到IO线程池(sub reactor 线程池)的某个IO线程上,由它负责SocketChannel的读写和编解码工作。Acceptor线程池仅仅只用于客户端的登陆、握手和安全认证,一旦链路建立成功,就将链路注册到后端subReactor线程池的IO线程上,由IO线程负责后续的IO操作。
其职责分工如下:
Netty使用的线程模型
Netty的线程模型不是一成不变的,它实际取决于用户的启动参数配置。通过设置不同的启动参数,Netty可以同时支持Reactor单线程模型、多线程模型和主从Reactor多线程模型。
3.协议
Netty默认提供了对Google的高性能序列化框架Protobuf的支持。Java原生的序列化性能较差,而经过Protobuf序列化后的码流只有Java序列化的四分之一左右。且用户也可以通过实现Netty的编解码的接口,来实现其他高性能的序列化框架。
拓展: 影响序列化性能的关键因素总结如下:
-
序列化后码流的大小(网络带宽的占用)
-
序列化和反序列化的性能(CPU资源占用)
-
是否支持跨语言(异构系统的对接和开发语言切换)
4.其他
1. 零拷贝---Netty的接收和发送ByteBuffer采用了零拷贝
零拷贝是指计算机执行IO操作时,CPU不需要将数据从一个存储区域复制到另一个存储区域,进而减少上下文切换以及CPU的拷贝时间。它是一种IO操作优化技术。
2. 内存池---Netty提供了基于内存池的缓冲区重用机制
3. 采用了串行无锁化设计
Netty采用了串行无锁化设计,在IO线程内部进行串行操作,避免多线程竞争导致的性能下降。