java-netty-Netty in Action 5th-ch1-Netty and Java NIO APIs
前言
netty 学习 基于 netty in action 5th, 官网资料,网络博客等
1.1 Why Netty?
netty 是一个中间层的抽象
"all problems in computer science can be solved by another
level of indirection"
netty 是一个中间层的抽象,因为底层的网络编程的各种问题
1.1.1 Not all networking frameworks are alike
Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients.
"Quick And Easy"是如何保证的
Netty 的实现者汲取了 它人实现 FTP, SMTP, HTTP, WebSocket, SPDY and various binary and text-based legacy protocols 中遇到的问题,take great care in its design。并没有在可扩展,灵活性,稳定性上做出妥协。
2011年Netty 之父离开redhat加入Twitter, 所以redhat、twitter是netty的两个主要贡献公司,
netty的许多特性也是众多大公司项目需求导致的。
1.1.2 Netty boasts a rich feature set
- zero copy capable rich byte buffer
参考:https://segmentfault.com/a/11...
java io 会涉及到copy,
比如,一个请求有两个bytebuffer, 分别是请求头,和请求正文,那么,我们接收请求后的处理是,定义一个大的bytebuffer将这两个bytebuffer的内容copy到大数组中。
netty可以用CompositeByteBuf,利用一个抽象的逻辑Buffer来避免这个事情。
比如,java 的文件读写,我们一般会定义一个小数组,在输入流和输出流之间读写,这样就涉及了一次copy.
netty 的FileRegion 利用Java NIO FileChannel.transfer可以避免这个问题。
还有其它的情况。
- 统一的api
传统的 Java I/O API 在应对不同的传输协议时需要使用不同的类型和方法。比如
- java.net.Socket 和 java.net.DatagramSocket 它们并不具有相同的超类型
- tcp,udp,ftp...多种协议扩展会很麻烦
bio、nio、aio api 也是不同的
- Extensible event module
1.2 Asynchronous by design
- callback java
- Future
参考:https://www.cnblogs.com/cz123...
FutureTask:
构造函数接收一个Callable对象,这个对象只有一个call 方法,有返回值,会抛出异常。
FutureTask继承Runnable,说明可以作为一个参数传到Thread中,其中的run方法,调用的是Callable中的call方法。
FutureTask继承Future,Future中有isDone,cancel,is...方法可以控制Callable的call方法返回状况。
1.3 Blocking versus non-blocking IO on the JVM
1.3.2 Non-blocking IO basics
jdk1.4的nio,和jdk1.7的nio2的api不同,但是底层的一些特性是相同的,比如都是用bytebuffer做为数据的容器。
ByteBuffer:
BYTEBUFFER
A ByteBuffer is fundamental to both NIO APIs and, indeed, to Netty. A ByteBuffer can
either be allocated on the heap or directly, which means its stored outside of the HeapSpace. Usually, using a direct buffer is faster when passing it to the channel, but the
allocation/deallocation costs are higher. In both cases, the API for a ByteBuffer is the same,
which provides a unified way of accessing and manipulating data. A ByteBuffer allows the
same data to be easily shared between ByteBuffer instances without the need to do any
memory copying.
bytebuffer,要注意,一个是堆外内存,适用于频繁使用的临时区域
(一般java读取数据,都是后现将数据从堆内copy一份到堆外,然后再操作)
selector
简单说,就是Selector会不断的轮询注册在其上的通道(Channel),如果某个通道发生了读写操作,这个通道就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以取得就绪的Channel集合,从而进行后续的IO操作。一个多路复用器(Selector)可以负责成千上万的通道(Channel),没有上限。这也是JDK使用了epoll代替传统的select实现,获得连接句柄(客户端)没有限制。那也就意味着我们只要一个线程负责Selector的轮询,就可以接入成千上万个客户端,这是JDK NIO库的巨大进步
Nio Vs Aio
nio和aio 区别:在NIO的基础上引入了异步通道的概念,并提供了异步文件和异步套接字通道的实现,从而在真正意义上实现了异步非阻塞,之前的NIO只是非阻塞而并非异步。AIO不需要通过对多路复用器对注册的通道进行轮询操作即可实现异步读写,从而简化NIO编程模型。
1、nio 是围绕selector,selector上注册的serversocketchannel,socketchannel,及确定的注册事件。
2、aio 简化了nio操作,当一个event(Accept,Connect,read,write)发生时,CompletionHandler会处理,使得用户专注于业务逻辑。
1.4 NIO problems and how Netty comes to the rescue
一、Nio 依赖底层的操作系统,有跨平台问题。
When using NIO you often find that your code works fine on Linux, for example, but has problems on Windows.
同时,jdk1.4支持nio, 1.7 支持nio2. 如果是jdk1.6 怎么办
最后,到目前位置,nio.2 支持tcp, 不支持udp.
二、无法扩展
作为nio的核心,bytebuffer 无法扩展,私有构造函数。netty 实现了自己的bytebuffer.
三、NIO对缓冲区的聚合和分散操作可能会操作内存泄露
四、 epoll bug