美文网首页网络
【高性能网络编程】基础知识2 IO多路复用与Reactor 模式

【高性能网络编程】基础知识2 IO多路复用与Reactor 模式

作者: 交藤 | 来源:发表于2021-05-11 13:46 被阅读0次

    对比几种不同的 IO

    1. 阻塞IO

      应用进程被阻塞,直到数据从内核缓冲区复制到应用进程缓冲区中才返回。
      特点:阻塞进程,CPU 利用率高

    1. 非阻塞IO
      应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的轮训(增加了系统调用)来获知 I/O 是否完成。
      特点:不阻塞进程,轮训增加了 CPU 消耗

    2. IO复用

      单个进程可以等待多个套接字中的任何一个变为可读。这一过程会被阻塞,当某一个套接字可读时,把数据从内核复制到进程中。
      特点:阻塞进程,无轮训 CPU

    3. 异步 I/O

      应用进程执行阻塞的调用会立即返回,应用进程可以继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。
      特点:不阻塞进程,无轮训 CPU

    同步IO 与 异步IO

    同步与异步体现在 内核态到用户态的数据拷贝 是否阻塞等待
    IO复用 非异步IO,只是允许等待的 fd事件 变多了

    • 同步IO:包含阻塞IO非阻塞IOIO复用
    • 异步IO:即异步IO

    需要注意IO复用本质是 同步IO

    IO多路复用 异步IO

    Epoll 与 Select

    fd :文件描述符

    Select

    1. 描述符有限,最大值 1024
    2. 查询 fd 均遍历数组,O(n) 复杂度
    3. 轮训就绪状态的 fd 均需要传入所有 fd
    4. 每次轮训传入fd 都会触发用户态到内核态的拷贝

    Epoll

    1. 描述符无限制
    2. fd 存放结构为红黑树,就绪 fd 事件触发回调插入就绪链表,读写 fd 事件的性能 O(logN),查询就绪 fd 事件性能 O(1) (直接读取就绪链表)
    3. 通过就绪链表存放就绪状态的 fd 事件,查询时直接返回就绪链表
    4. 红黑树与就绪链表直接存放内核态中,避免了用户态与内核态间的大量拷贝 (epoll_wait 拷贝少量就绪 fd 句柄)
    
    int epoll_create(int size);
    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
    int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
    
    // epoll_create 创建 epoll,设定 fd 数量(内核开辟存储空间)
    // epoll_ctl 管理 fd 事件的监控(红黑树的插入/删除)
    // epoll_wait 返回相应就绪的事件的 fd(内核态向用户态拷贝就绪链表内的就绪事件)
    
    epoll

    LT 与 ET

    • LT(水平触发):epoll_wait 不会删除就绪链表,每次 epoll_wait 均返回
    • ET(边缘触发):epoll_wait 后会删除就绪链表
    ET 下读写方式:
        只要可读,就一直读,直到读完或失败
        只要可写,就一直写,直到数据发送完或失败
    
    【经典问题】
    1. LT 下 ‘可写就绪’ 一直触发,怎么解决
        要写数据时,添加fd可写事件通过 epoll_crt 添加到epoll里,写完后移除。
    2. TCP accept 
        接收到连接到达时, while(accept) 循环处理所有连接,避免连接丢失
    

    Reactor

    反应堆模式
    也叫 Dispatcher 模式,即 I/O 多路复用监听事件,收到事件后,根据事件类型分配(Dispatch)给某个线程。

    单 Reactor 单进程 / 线程

    只适用于业务处理非常快速的场景,不适用计算机密集型的场景。需要 handler 尽量快速地执行处理,否则会影响吞吐。

    • Reactor 对象的作用是监听和分发事件;
    • Acceptor 对象的作用是获取连接;(连接建立的事件,则交由 Acceptor 对象进行处理)
    • Handler 对象的作用是处理业务;(不是连接建立事件, 则交由当前对应的 Handler 来处理)
    单 Reactor 单进程 / 线程

    单 Reactor 多进程 / 线程

    事件处理由 worker 线程池负责,解决了单线程下 handler处理耗时导致吞吐降低的问题。
    但还存在大并发量情况下 dispatch 速率影响吞吐的问题。

    单 Reactor 多进程 / 线程

    多(主从) Reactor 多进程 / 线程

    Reactor 只负责 dispatch 事件,因此为了充分利用cpu,可以通过多 Reactor 并行 dispatch。
    主从 Reactor,主负责建立连接(处理accept),子 Reactor 负责 dispatch 事件到 worker 线程池

    多(主从) Reactor 多进程 / 线程

    相关文章

      网友评论

        本文标题:【高性能网络编程】基础知识2 IO多路复用与Reactor 模式

        本文链接:https://www.haomeiwen.com/subject/ijeidltx.html