【Netty】五种经典 IO 模型详解,附各种模型流程图及流程详解

相关概念

  • 同步:线程自己去获取结果(一个线程)

  • 异步:线程自己不去获取结果,而是由其它线程送结果(至少两个线程)

  • 同步阻塞、同步非阻塞、同步多路复用、异步阻塞(没有此情况)、异步非阻塞

    IO模型 描述 特点 类比
    同步非阻塞 线程发起IO请求后,可以继续执行其他任务,但需要定期轮询检查IO操作是否完成 避免阻塞,但频繁轮询消耗CPU资源 小学生一直闹着要东西
    同步阻塞 线程发起IO请求后,必须等待IO操作完成才能继续执行其他任务 最简单但效率最低 大学生安静等东西,什么也不做
    同步多路复用 使用一个线程管理多个IO操作,通过select/poll/epoll等机制同时监控多个IO事件 可用较少线程处理大量IO请求 员工把要的东西不断告诉经理,经理不断告诉哪些东西到了,员工自己拿走
    异步非阻塞 线程发起IO请求后立即返回,由操作系统通过回调机制通知完成 完全不会阻塞线程,最灵活 员工把要的东西不断告诉经理,经理同意提供,并在准备好后直接送给员工
    异步阻塞 不存在此组合 异步操作本身就意味着不会阻塞线程
  • fd:文件描述符,一个非负整数,用于标识打开的文件、套接字或其他 IO 资源。每个 fd 对应一个内核中的文件表项,包含文件的偏移量、状态等信息

  • select:一个系统调用。它允许一个线程监控多个 fd 的状态变化,并在任一 fd 就绪时返回给调用线程

工作流程

整体流程

  1. 请求数据:用户进程发起 read() 请求,请求网络中的某个数据
  2. 转交任务:用户进程将 read() 任务交给本地操作系统内核空间处理(进程无法自己处理)
  3. 网络请求:内核接收请求后,向服务器发出 read() 请求,等待数据回传
  4. 复制数据:内核接收回传数据后,将缓冲区内容复制到本地
  5. 返回数据:内核空间将本地数据返回给用户进程

操作系统内核态两阶段

  • 等待数据阶段:等待外部数据到达内核缓冲区

  • 复制数据阶段:将数据从内核缓冲区复制到用户进程空间

IO 模型

一、阻塞 IO

  1. 定义:应用进程在发起读取请求后会一直阻塞,直到整个IO操作(包括等待数据和复制数据两个阶段)完成。这是最简单但效率最低的IO模型。

  2. 工作流程

    1. 应用进程向内核发起 recfrom 读取数据
    2. 内核请求服务器,并请求远程数据(应用进程阻塞)
    3. 数据报到达内核缓冲区,内核复制数据到应用空间
    4. 数据复制完成,内核向应用程序返回成功指令
    5. 应用进程读取应用空间数据报,并进行处理
  3. 流程图

二、非阻塞 IO

  1. 定义:应用进程不会在等待数据阶段被阻塞,但需要不断轮询检查数据状态,这会消耗CPU资源。数据复制阶段仍然是阻塞的,这是它与异步IO的主要区别。
  2. 工作流程
    1. 应用进程向内核发起 recfrom 读取数据
    2. 内核立即返回 EWOULDBLOCK 错误码,内核请求服务器,并请求远程数据报(应用进程不阻塞)
    3. 应用进程不断向内核发起 recfrom 读取数据,直至数据准备好
    4. 数据报到达内核缓冲区,内核复制数据到应用空间
    5. 数据复制完成,内核向应用程序返回成功指令
    6. 应用进程读取应用空间数据报,并进行处理
  3. 流程图

三、⭐ 多路复用

  1. 核心思想:由一个专门的线程担任选择器(Selector,也叫多路复用器)同时监控多个网络连接(文件描述符fd),集中管理多个客户端连接的IO事件,实现一个线程处理多个连接的效果

  2. 优点:多路复用IO模型允许一个线程管理多个连接,大大提高了系统的并发处理能力,特别适合高并发场景。而阻塞IO模型中每个连接需要一个线程来处理,并发能力低

  3. 相关概念

    1. Socket 对象:一个可以 IO 的资源, 发送数据就是对 Socket 进行写操作, 接收数据就是读 Socket
    2. fd 文件描述符:一个非负整数,代表一个已经打开的文件、管道、网络套接字或其他 I/O 资源
    3. select:多路复用 I/O 模型的系统调用,可以同时监视多个文件描述符的状态变化。有容量限制(默认1024个fd)和性能瓶颈(每次都需要将所有fd从用户态拷贝到内核态)
    4. epoll:Linux 特有的高性能I/O多路复用机制,解决了select的主要缺点。它支持的fd数量受系统内存限制,使用事件通知机制避免了无效的轮询,并通过内存映射减少了数据拷贝
  4. 工作流程

    1. 应用进程向内核请求数据,将 fd 传递给 select(或者其他IO复用API)
    2. 线程阻塞在 select 操作上,由 select 侦测 fd 是否准备就绪
    3. 当存在准备就绪的 fd 时,select 返回数据可读状态
    4. 应用程序收到 select 的可读状态时,调用 recvfrom 读取数据(需要阻塞)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值