Netty源码分析之NIO

1、Socket和IO模型

1、Socket

Socket是两台主机之间逻辑连接的端点。TCP/IP是传输层协议,定义数据如何在忘了中进行传输。HTTP是应用成协议,主要用来定义规范,包装数据,方便数据处理。Socket是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议、本地主机的IP地址、本地进程的协议端口、远程主机的IP地址、远程进程的议
端口(IP+Port+Protocol)

2、Socket通信流程

在这里插入图片描述

3、IO模型

Java 共支持 3 种网络编程模型/IO 模式:BIO(同步并阻塞)、NIO(同步非阻塞)、AIO(异步非阻塞)

1、BIO(同步阻塞)

同步堵塞IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制优化

在这里插入图片描述
问题:

  • 每个请求需要创建独立的线程,创建线程是需要JVM内存开销的,默认好像是1kb,如果说并发比较大,资源占用比较大(调小)
  • 瞬时并发,请求回落,线程浪费严重(线程池)
  • 线程在业务处理过程中,可能会碰到IO,消费者数据消费更不上生产者线程等等,这些势必会导致线程堵塞等待(reactor-stream)
  • 连接建立后,当前线程中发现inputStram中没有数据可读,也会导致线程堵塞
NIO(同步非阻塞)

同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),以事件驱动为基础,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有 I/O 请求就进行处理

在这里插入图片描述
缺点:

  • NIO线程组需要指定大小,如果估算配置相差较大,也会造成浪费或不足
  • 线程在业务处理过程中,可能会碰到IO,消费者数据消费更不上生产者线程等等,这些势必会导致线程堵塞等待(reactor-stream)
  • 编写,理解代码相对来说复杂那么一点
AIO(异步非阻塞)

AIO 引入异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用

4、NIO编程

Java NIO 全称java non-blocking IO ,是指 JDK 提供的新 API。从 JDK1.4 开始,Java 提供了一系列改进的输入/输出的新特性,被统称为 NIO(即 New IO),是同步非阻塞的。

  1. NIO 有三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器)
  2. NIO是 面向缓冲区编程的。数据读取到一个缓冲区中,需要时可在缓冲区中前后移动,这就增加了处理过程中的灵活性,使用它可以提供非阻塞式的高伸缩性网络
  3. Java NIO 的非阻塞模式,使一个线程从某通道发送请求或者读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此,一个线程请求写入一些数据到某通道,但不需要等待它完全写入, 这个线程同时可以去做别的事情 通俗理解:NIO 是可以做到用一个线程来处理多个操作的。假设有 10000 个请求过来,根据实际情况,可以分配50 或者 100 个线程来处理。不像之前的阻塞 IO 那样,非得分配 10000 个

区别

  • BIO是以流方式处理数据,NIO以缓冲区处理数据,缓冲区IO效率比流IO效率高,为啥??嘿嘿,等下说
  • BIO是阻塞的,NIO是非阻塞的,内部通过事件驱动,taskQueue,Thread实现
  • IO模型内部结构设计不一样,BIO是Thread-per-request,NIO是SocketChannel,Buffer,Selector
为什么缓冲区IO效率高于流IO?
  • 流与块
    IO和NIO最重要的区别就是数据打包和传输的方式,IO以流的方式处理数据,而NIO以块的方式处理数据。
    面向流的IO一次处理一个字节数据:一个输入流产生一个字节数据,一个输出流消费一个字节数据。为流式数据创建过滤器非常容易,连接一个过滤器,以便每个过滤器只负责复杂处理机制的一部分。不利的一面是,面向流的IO非常慢
    面向块的IO一次处理一个数据块,按照处理数据比按照流处理数据要块很多。但是面向块的IO缺少一些面向流的IO所具有的优雅性和简单性。
    IO包和NIO已经很好的集合了,java.io.* 已经以NIO为基础重新实现了,所以它现在可以利用NIO的一些特性。例如,java.io.* 包中的一些类包含以快的形式读取数据的方法,这使得即使在面向流的系统中,处理速度也会更快。
  • channel和stream:
    方向性:channel数据是双向通行(read/write) ,stream是单向通行的。
    channel是必须和buffer结合使用的,stream可以和buffer配套,也可以不用。
    channel是可以设置为阻塞和非阻塞的。流本身就是阻塞的
NIO核心组件关系原理

在这里插入图片描述

  1. 每个 channel 都会对应一个 Buffer
  2. Selector 对应一个线程, 一个线程对应多个 channel(连接)
  3. 每个 channel 都注册到 Selector选择器上
  4. Selector不断轮询查看Channel上的事件, 事件是通道Channel非常重要的概念
  5. Selector 会根据不同的事件,完成不同的处理操作
  6. Buffer 就是一个内存块 , 底层是有一个数组
  7. 数据的读取写入是通过 Buffer, 这个和 BIO , BIO 中要么是输入流,或者是输出流, 不能双向,但是
    NIO 的 Buffer 是可以读也可以写 , channel 是双向的.
数据传输流程

在这里插入图片描述

Selector大致执行流程

在这里插入图片描述
只有在通道真正有读写事件发生时,线程才会进行读写,提高了线程利用率,减少上下文切换开销,避免创建多个线程处理导致内存开销

值得注意的对象和方法

Selector有几个重要方法需要注意:

  • Selector.open() : //得到一个选择器对象
  • selector.select() : //阻塞 监控所有注册的通道,当有对应的事件操作时, 会将SelectionKey放入集合内部并返回事件数量
  • selector.select(1000): //阻塞 1000 毫秒,监控所有注册的通道,当有对应的事件操作时, 会将SelectionKey放入集合内部并返回
  • selector.selectedKeys() : // 返回存有SelectionKey的集合

SelectionKey什么意思?

在这里插入图片描述
SelectionKey:A token representing the registration of a SelectableChannel with a Selector

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白鸽呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值