Netty快速学习2-多路复用技术与Reactor模式

基本概念弄清楚是学好 Netty的前提

前言

这里总结一些基本概念 IO多路复用技术: select、poll、epoll
和 基于事件驱动的Reactor模式概念。

IO网络模型

这里复习一下 :
一共五种IO的模型:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO 和 异步IO
前面四种IO模型都是 同步IO

问题: 什么是同步异步 ? 什么是阻塞非阻塞?
Linux操作系统的体系架构分为用户态内核态(或者用户空间和内核)
IO操作分为两步:
1. 应用程序线程发起IO请求,调用系统函数,等待内核将数据准备
2. 实际的IO操作过程,将数据从内核拷贝到应用程序的进程中

在这里插入图片描述
回答 什么是同步异步 ? 什么是阻塞非阻塞?的问题:
发起IO请求的线程是否可以去做别的事情可以=非阻塞 不可以=阻塞
是否需要发起IO线程主动去取内核数据? 是=同步 否=异步

IO多路复用技术

什么是IO多路复用?
简单来说:就是使用一个或者几个线程处理多个TCP连接,它最大优势是减少系统开销小,不必创建过多的进程/线程,也不必维护这些进程/线程。

借用网上不错博客图片:
在这里插入图片描述
IO多路复用技术 技术常见的实现有 select poll epoll

文件描述符fd

在Linux系统中一切皆文件,一个 Linux 进程可以打开成百上千个文件,为了表示和区分已经打开的文件,Linux 会给每个文件分配一个编号(一个 ID),这个编号就是一个整数,被称为文件描述符(File Descriptor)

一个进程创建时候,Linux为每一个进程自动打开3个标准文件( stdin、stdout、stderr),其文件描述符为0,1,2

所有的网络请求都用一个fd来标识,在windows中称为句柄(指针的指针)。

select

  1. 监视文件3类描述符: writefds、readfds、和exceptfds
  2. 调用后select函数会阻塞住,等有数据 可读、可写、出异常 或者 超时
  3. select采用轮询方式扫描全部文件描述符
  4. 每次调用 select(),需要把 fd 集合从用户态拷贝到内核态,并进行遍历
  5. 单个进程打开的fd有限制,默认是1024,可修改宏定义,但效率仍然慢

poll

select() 和 poll() 系统调用的大体一样,要把 fd 集合从用户态拷贝到内核态,并进行遍历。
最大区别是: poll没有最大文件描述符限制(使用链表的方式存储fd)

epoll

对比select和poll,epoll更加灵活,没有描述符限制,所支持的fd上限是操作系统的最大文件句柄数,1G内存大概支持10万个句柄。

使用事件通知方式处理fd,无需轮询所有fd,用户态拷贝到内核态只需要一次,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用callback的回调机制来激活对应的fd。

epoll调用了 Linux内核函数:

  1. epoll_create() 在Linux内核里面申请一个文件系统 B+树,返回epoll对象,也是一个fd
  2. epoll_ctl() 操作epoll对象,在这个对象里面修改添加删除对应的链接fd, 绑定一个callback函数, 一旦该fd就绪,内核就会采用callback的回调机制来激活对应的fd
  3. epoll_wait() 判断并完成对应的IO操作

epoll 缺点就是编程模型比select/poll 复杂。

Reactor模式

Reactor模式(反应器设计模式),是一种基于事件驱动的设计模式,在事件驱动的应用中,将一个或多个客户的服务请求(demultiplex)和调度(dispatch)给应用程序。

Reactor模式基于事件驱动,适合处理海量的I/O事件,属于同步非阻塞IO(NIO)

BIO,NIO,AIO

  1. BIO (Blocking I/O): 同步阻塞 I/O 模式,java1.4之前都是BIO
  2. NIO (Non-blocking/New I/O): NIO 是⼀种同步⾮阻塞的 I/O 模型,Java1.4引入
  3. AIO (Asynchronous I/O): AIO 也就是 NIO 2.0 (异步⾮阻塞的 IO 模型), 在 Java 1.7 中引⼊。

Reactor分类

单线程Reactor模型

单线程Reactor模型
一个Acceptor线程作为NIO服务端和客户端,接收客户端的TCP连接,向服务端发起TCP连接,handle里面的IO/非IO操作都有此线程代理完成
Handle:文件句柄(window)或称为文件描述符(Linux),内核监控的对象

多线程Reactor模型

在这里插入图片描述
一个Acceptor线程,一组NIO线程,一般是使用自带的线程池,包含一个任务队列和多个可用的线程。

此模型中,将Handler中的IO操作和非IO操作分开,
要IO操作的线程称为IO线程
非IO操作(例如:decode compute encode)的线程称为工作线程

IO操作阶段交给Acceptor线程来做,非IO操作阶段采用线程池来处理

主从Reactor模型

在这里插入图片描述
Acceptor不在是一个线程,而是一组NIO线程;IO线程也是一组NIO线程,这样就是两个线程池去处理接入连接和处理IO,是Netty推荐使用的线程模型

主Reactor 负责监听连接,将accept连接交给Sub Reactor处理,主Reactor用于响应连接请求。
从Reactor 处理accept连接,从Reactor用于处理IO操作请求。

为什么Netty使用NIO而不是AIO?

常见问题:为什么Netty使用NIO而不是AIO,是同步非阻塞还是异步非阻塞?

答案:
在Linux系统上,AIO的底层实现仍使用epoll,与nio相同,因此在性能上没有明显的优势。
Netty整体架构是reactor模型,采用epoll机制,所以往深的说,还是IO多路复用模式,所以也可说netty是同步非阻塞模型。

参考资料: https://github.com/netty/netty/issues/2515

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值