当前位置: 首页 > news >正文

经典网络模型

文章目录

  • 网络演变过程
    • 1、阻塞IO(BIO)
      • 实现
      • 缺点
    • 2、非阻塞IO(NIO)
      • 实现
      • 改进后
      • 设置非阻塞IO
      • 缺点
    • 3、IO多路复用第一版(select/poll)
      • 问题点
      • 改进
      • 缺点
    • 4、IO多路复用第二版(epoll)
    • 5、信号驱动IO
      • 区别
      • 缺点
    • 6、异步IO(AIO)
      • 区别
    • 小总结
  • 经典网络模型
    • 1、单Reactor单线程
      • 经典实现
    • 2、单Reactor线程池
    • 3、多Reactor多线程(多进程)
    • 4、Proactor

网络演变过程

linux内核演变:
在这里插入图片描述

1、阻塞IO(BIO)

实现

  • 简单的c/s模型,通常一个client分配一个线程处理(可以使用队列+线程池优化模型)

缺点

  • 并发数量少(线程有限)
  • 线程上下文切换影响性能(可用线程池缓解)

2、非阻塞IO(NIO)

实现

BIO和NIO的区别在于内核中数据尚未就绪时:

  • 阻塞IO一直处于阻塞状态,直到数据就绪并从内核态拷贝到用户态后返回
  • 非阻塞IO直接返回用户态EWOULDBLOCK错误

改进后

可以在一个线程中管理多个client

设置非阻塞IO

  • socket方法创建时候第二个参数type设置SOCK_NONBLOCK
  • fcntl方法第三个参数设置O_NONBLOCK

缺点

需要不断轮训询问内核数据是否就绪,涉及到很多无效的系统调用(system call)

3、IO多路复用第一版(select/poll)

问题点

非阻塞socket不知道什么时候有数据,所以需要主动询问。

改进

  • 每个client都要询问 —> 批量询问(系统调用次数 O(n) —> O(1))
  • 从主动询问变成等待通知(系统调用次数下降)

缺点

  • 每次查询都会把多个client从用户态拷贝到内核态。(管理百万级别及以上的时候会带来很大开销)
  • 处理有响应的client的时候要遍历所有client判断是否有响应。(模糊通知

4、IO多路复用第二版(epoll)

在这里插入图片描述

改进:

  • 监听fd每次全量维护 —> 监听fd初始化 + 增量维护
  • 模糊通知 —> 明确通知(内部使用就绪列表)

5、信号驱动IO

在这里插入图片描述

区别

无需进程主动去check活跃的socket,把检查工作交给内核。

缺点

当有大量IO操作时,信号较多,SIGIO处理函数不能及时处理可能导致信号队列溢出,而且内核空间与用户空间的频繁信号交互性能也较低

6、异步IO(AIO)

区别

  • epoll(同步非阻塞IO)封装了一个异步事件的通知机制,不负责IO读写操作
  • iocp(异步IO)封装了异步的消息事件的通知机制,同时封装了部分IO操作

iocp将接收发送等io操作也封装到了内核中,对处理大量短连接比较高效。

linux也有AIO,如gcc AIOlibaio等。
流程如下:
在这里插入图片描述

小总结

在这里插入图片描述

经典网络模型

1、单Reactor单线程

在这里插入图片描述

定义:单线程主要针对IO操作而言,I/O中的accept()、read()、write()都是在一个线程完成的。
问题:

  • IO操作和业务逻辑处理操作在一个线程上,大大降低了I/O请求的处理效率。
  • 无法充分利用和发挥多核 CPU 的性能。
  • 可靠性问题,线程意外终止,或者进入死循环,会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障。

经典实现

redis:
使用单Reactor单线程,在6.0版本前,核心业务部分使用单线程。官方数据:10万QPS。
6.0版本之后多线程处理网络数据的读写和协议的解析,单线程执行命令。QPS还能提高1~2倍。

为什么用单线程

  • 抛开持久化不谈,Redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度,因此多线程并不会带来巨大的性能提升。
  • 多线程会导致过多的上下文切换,带来不必要的开销。
  • 引入多线程会面临线程安全问题

单线程的缺点:顺序执行影响后续事件

2、单Reactor线程池

在这里插入图片描述

改进:引入了线程池,用来专门处理业务逻辑操作,提升I/O响应速度,利用多 CPU 的处理能力。
问题:

  • 多线程数据共享和访问比较复杂。
  • 管理百万级连接、高并发大数据量时,单个Reactor线程仍然会效率比较低下。

3、多Reactor多线程(多进程)

在这里插入图片描述

改进:扩展了Reactor。引入多个Reactor。也称为主从结构。父线程和子线程的职责明确。

扩展Reactor可以是多线程也可以是多进程。

方式资源分配经典实现
多线程线程之间如果涉及资源竞争的话,需要通过锁来保证同步netty、memcached等
多进程需要进程间通信nginx等

4、Proactor

在这里插入图片描述
对比Reactor

  • Proactor 在处理高耗时 IO 时的性能要高于 Reactor,但对于低耗时 IO 的执行效率提升并不明显
  • Proactor 的异步性使其并发处理能力要强于 Reactor
  • Proactor 的实现逻辑复杂,编码成本较 Reactor 要高很多
  • Proactor 的异步高度依赖于操作系统对于异步的支持。若操作系统对异步的支持不好,Proactor 的性能还不如 Reactor
  • Reactor 是同步非阻塞网络模型,Proactor 是异步非阻塞网络模型

问题:Linux 对 AIO支持的不太友好


http://www.mrgr.cn/news/68043.html

相关文章:

  • 青少年编程与数学 02-003 Go语言网络编程 12课题、Go语言Soket编程
  • Linux系列-进程的状态
  • 宠物空气净化器是养宠智商税吗?真实测评霍尼韦尔、希喂、米家
  • docker 启动 neo4j
  • Perforce《2024游戏技术现状报告》Part2:游戏引擎、版本控制、IDE及项目管理等多种开发工具的应用分析
  • 5分钟利用SD+剪映制作爆款的山水画艺术体视频,快速涨粉(含完整的操作步骤)
  • brainpy 动力学编程基础
  • 最新kubernetes搭建(k8s)(已成功搭建)
  • 【科普】卷积、卷积核、池化、激活函数、全连接分别是什么?有什么用?
  • 【软考】错题总结:1106
  • [CUDA] 判断一个指针是GPU还是CPU
  • 远程控制项目第四天 功能实现
  • Claude Prompt:博弈天平|缘起自李继刚老师的提示词
  • 使用PyQt5设计一个简易计算器
  • 【测试】【Debug】pytest运行后print没有输出
  • CPU Study-Multi-Port Cache
  • golang函数
  • 使用开源Embedding模型嵌入高维空间向量
  • Linux命令--paste
  • 【大模型系列】Grounded-VideoLLM(2024.10)
  • Java学习篇之JVM 调优
  • linux进程的状态之环境变量
  • 【贪心算法】No.1---贪心算法(1)
  • linux 进程调度学习笔记
  • 迭代解法:Jacobi、Gauss-Seidel、SOR
  • CPU Study - Branch Prediction