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

posted @ 2022-05-08 18:28  AlbertXe  阅读(26)  评论(0编辑  收藏  举报