JAVA网络编程 IO NIO Netty
基本概念
同步与异步: AB顺序执行 AB同时执行
阻塞与非阻塞: 阻塞指 线程处于阻塞状态时 无法从事其他任务,只有条件就绪就行 比如ServerSocket新连接建立完毕,或者数据读取、写入操作完成;非阻塞则是不管IO操作是否结束,直接返回
我们熟悉的File 输入输出流 交互方式是同步、阻塞的方式;
IO 同步阻塞
代码简单 效率差
Socket、ServerSocket、HttpURLConnection 也归类到同步阻塞 IO 类库,因为网络通信同样是 IO 行为;是input和output流
NIO 同步非阻塞
Channel(通道)、Buffer(缓冲区)、Selector(选择器)
Channel
- 双向 可读可写 流是单向
- 支持异步读写
- 必须通过Buffer操作
Buffer
- channel通过buffer操作数据
- NIO读写数据的中转池
使用 Buffer 读写数据一般遵循以下四个步骤:
1.写入数据到 Buffer;
2.调用 flip() 方法;buffer写切换到读
3.从 Buffer 中读取数据;
4.调用 clear() 清空Buffer方法或者 compact() 清空已读数据 方法,任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。
示例:
public static void copyFileUseNIO(String src,String dst) throws IOException{
//声明源文件和目标文件
FileInputStream fi=new FileInputStream(new File(src));
FileOutputStream fo=new FileOutputStream(new File(dst));
//获得传输通道channel
FileChannel inChannel=fi.getChannel();
FileChannel outChannel=fo.getChannel();
//获得容器buffer
ByteBuffer buffer=ByteBuffer.allocate(1024);
while(true){
//判断是否读完文件
int eof =inChannel.read(buffer);
if(eof==-1){
break;
}
//重设一下buffer的position=0,limit=position
buffer.flip();
//开始写
outChannel.write(buffer);
//写完要重置buffer,重设position=0,limit=capacity
buffer.clear();
}
inChannel.close();
outChannel.close();
fi.close();
fo.close();
}
Selector
线程上下文切换开销会在高并发时变得很明显,这是同步阻塞方式的低扩展性劣势
- Selector是一个对象
- 可以注册到多个Channel上,监听channel上发生的事件,决定channel的读写;这样就可以通过一个Selector管理多Channel,处理大量的网络连接
- 一个线程处理所有的Channel
- 节约线程之间的切换对操作系统来说代价是很高
主要步骤和元素:
- 首先,通过 Selector.open() 创建一个 Selector,作为类似调度员的角色。
- 然后,创建一个 ServerSocketChannel,并且向 Selector 注册,通过指定 SelectionKey.OP_ACCEPT,告诉调度员,它关注的是新的连接请求。
- 注意,为什么我们要明确配置非阻塞模式呢?这是因为阻塞模式下,注册操作是不允许的,会抛出 IllegalBlockingModeException 异常。
- Selector 阻塞在 select 操作,当有 Channel 发生接入请求,就会被唤醒。
- 在 具体的 方法中,通过 SocketChannel 和 Buffer 进行数据操作
IO 都是同步阻塞模式,所以需要多线程以实现多任务处理。而 NIO 则是利用了单线程轮询事件的机制,通过高效地定位就绪的 Channel,来决定做什么,仅仅 select 阶段是阻塞的,可以有效避免大量客户端连接时,频繁线程切换带来的问题,应用的扩展能力有了非常大的提高
AIO
AIO编程中,发出一个事件(accept read write等)之后要指定事件处理类(回调函数)
Netty
基础通信组件 服务间的数据通信
完全可以基于Netty来实现自己的HTTP服务器,FTP服务器,UDP服务器,RPC服务器,WebSocket服务器,Redis的Proxy服务器,MySQL的Proxy服务器等等
Netty特点
- 高并发 基于NIO同步非阻塞 并发性能得到了很大提高
- 传输好 以来零拷贝特性 减少不必要的内存拷贝
- 封装好 实现了NIO操作的很多细节 方便调用
- 内存池设计:申请的内存可以重用,主要指直接内存。内部实现是用一颗二叉查找树管理内存分配情况
- 串形化处理读写:避免使用锁带来的性能开销。
- 高性能序列化协议:支持 protobuf 等高性能序列化协议。
- 统一API 适用不同的协议
Netty原理分析
TODO