导语
netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.
Netty简介
上面的导语是netty官方的一个介绍,netty 其实就是基于事件驱动,快速开发高并发,高可靠性的服务和客户端的一个开源框架。主要特性有以下几点。
设计
- 统一的API,适用于不同的协议(阻塞和非阻塞)
- 基于灵活、可扩展的事件驱动模型
- 高度可定制的线程模型
- 可靠的无连接数据Socket支持(UDP)
性能
- 更好的吞吐量,低延迟
- 更省资源
- 尽量减少不必要的内存拷贝
安全
- 完整的SSL/ TLS和STARTTLS的支持
易用
- 完善的Java doc,用户指南和样例,社区很活跃
- 简洁简单
- 仅依赖于JDK1.5
Netty框架
核心部分
零拷贝
“Zero-copy” describes computer operations in which the CPU does not perform the task of copying data from one memory area to another.
上面是wiki的一描述,它通常是指计算机在网络上发送文件时,不需要将文件内容拷贝到用户空间(User Space)而直接在内核空间(Kernel Space)中传输到网络的方式,所谓的两个空间只是说明两个不一样的内存区域,通过减少不同内存区域的拷贝,减低cpu的消耗。下面有两张对比图
1、非零拷贝模式
2、零拷贝模式
Netty的零拷贝与实际定义还是有点出入,java是基于虚拟机的,其实都是用户空间,Netty中的零拷贝,更多的是一种数据的优化操作,比如多包合并处理上,netty是将各个包的地址记录下来,在逻辑上合成一个整体,实际存储还是独立的,这样减少内存拷贝,降低cpu消耗。
统一通讯API
netty提供了命名为 channel 统一异步IO接口,主要是为了解决java OIO,NIO API 不兼容,简化业务层的工作。
可扩展的事件模型
Netty has a well-defined event model focused on I/O. It also allows you to implement your own event type without breaking the existing code because each event type is distinguished from another by a strict type hierarchy. This is another differentiator against other frameworks.
Netty是通过ChannelEvent作为事件流载体,通过ChannelHander来做事件逻辑处理,channelHander又可分为INBoundHandler 和 OUTBoundHandler分别处理流入数据和流出数据,Event则通过sendDownStream 和 sendUpStream 在每个handler中流转,ChannelPipeline作为handler的容器,用户自定义的handler只要添加到pipe,就可以截取数据流做业务处理。
所有的数据流转,和执行过程都是在一个线程(EventLoop)上执行的,这种串行化的处理方式,让netty无锁化,无需处理数据竞争问题,提高了执行效率。
高级组件
编解码框架
netty提供里提供一套EncodeHandler 和 DecodeHandler,将业务逻辑从编解码分离,大家可以了解一下,有时间会对这块仔细说明
SSL / TLS Support
在netty中使用SSL也是很方便的,使用SSLEngine,SslHandler就可以
Http/WebSocket支持
Netty线程模型
Netty支持三种线程模型,分别是单线程模型,多线程模型,以及主从线程模型,重点会介绍主从多线程模型
单线程模型
从accpet连接到分发到handler处理业务,都在单线程中完成,模型简单,适合简单场景,不适合大并发场景。多线程模型
- Acceptor单独线程接受accpet连接请求,创建Channel,并移交给IO线程池
- IO线程池分配线程读取Channel数据,并分发handler处理相关业务
- Accpetor是单线程,如果期间执行鉴权,登陆等操作,出现拥堵,会有单点问题。
主从多线程模型
Acceptor线程池(NioEventLoopGroup)分配一个NioEventLoop接受连接请求,并创建Channel,并将Channel移交给IO线程池
I/O线程池((NioEventLoopGroup)分配一个NioEventLoop处理Channel数据,从Channel读数据,并将数据交给handler处理,handler处理完后,向Channel写数据
I/O线程池还可以处理定时任务,和系统任务。
这边多次提到NioEventLoop,许多个NioEventLoop构成NioEventLoopGroup,其主要的职能如下:
1. 作为Acceptor线程,负责处理客户端的请求接入
2. 作为Connecor线程,负责注册监听连接操作位,用于判断异步连接结果
3. 作为IO线程,监听网络读操作位,负责从SocketChannel中读取写报文
这张图很好的说明NioEventLoop的作用,以及Netty串行化的处理链。
1. 一个客户端Channel只能由一个NioEventLoop处理,避免并发资源竞争问题。
2. NioEventLoop的事件是分发给Netty的事件模型,这个模型可以参考上面的说明。
总结
本文主要介绍了Netty的原理,重点对Netty的串行化处理链,线程模型,数据模型做了说明,绕过了细节,希望对大家在大层面去理解Netty有帮助,更多的实践,以及细节,留在后续文章再说。