• 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

  • 相关阅读:
    Django: 获取头信息
    好用工具:火狐浏览器的境内境外版本区分
    Django: request.GET.get()
    es6: 展开运算符
    Vue: 配置axios基准路径并使用
    js: 获取Blob的值
    ApiPost: Error:ESOCKETTIMEDOUT
    Vue错误:Cannot read properties of undefined (reading '$router')
    git报错:error: Your local changes to the following files would be overwritten by checkout:
    Django: request.query_params取值
  • 原文地址:https://www.cnblogs.com/albertXe/p/16246360.html
Copyright © 2020-2023  润新知