剖析reactor网络模型

从五个方面掌握reactor网络模型

1.c/s架构网络编程流程

C/S(Client/Server):客户端=服务器结构。C/S结构在技术上很成熟,它的主要特点是交互性强、具有安全的存取模式、网络通信量低、响应速度快、利于处理大量数据。因为客户端要负责绝大多数的业务逻辑和UI展示,又称为胖客户端。它充分利用两端硬件,将任务分配到Client 和Server两端,降低了系统的通讯开销。C/S结构的软件需要针对不同的操作系统系统开发不同版本的软件,加之产品的更新换代十分快,已经很难适应百台电脑以上局域网用户同时使用。C/S 架构是一种典型的两层架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据库服务器端,客户端通过数据库连接访问服务器端的数据;另一种是Socket服务器端,服务器端的程序通过Socket与客户端的程序通信。

c/s架构流程图:

Linux采用的是reactor模型,windows采用的是iocp模型。不同的网络模型核心区别的地方是io的处理方式不同,其中涉及到用户与内核的交互和一些系统调用 

1)连接的建立 ----> 建立连接,接收连接

2)连接的断开

3)数据的接收

4)数据的发送

不同的网络模型对于这些问题处理有着不同的方式。

2.阻塞的io和非阻塞的io

阻塞io模型

io未就绪:可以理解为内核中的缓冲区是空的,对方还没有开始发送数据。 

当使用了阻塞的io模型时,使用accept/connect/read/write这些函数发起系统调用时,内核会检测io是否就绪,此时io从 未就绪--->就绪  这段过程是阻塞的,涉及到用户态数据和内核态数据拷贝时,从 开始拷贝--->拷贝结束 这段过程也是阻塞的。accept/connect/read/write这些函数不会立刻返回,会阻塞在当前用户线程。

 

                                                                 非阻塞io模型

 当使用了非阻塞的io模型时,使用accept/connect/read/write这些函数发起系统调用时,可以事先检测io是否就绪而立刻返回,会得到一个返回值,可以通过这个返回值检测当前io是否准备就绪。

/*
    fd: 文件描述符,读到文件末尾返回0。
    buf: 是接收数据的缓冲区。
    sz: 读取字节数的大小,不能超过buf的大小。
    返回值:成功返回实际读取的字节数,失败返回-1。
*/
connect(socket, addr, sz);
int n = read(fd, buf, sz);
int n = write(fd, buf, sz);

io的阻塞与非阻塞是由文件描述符fd属性决定的 fcncl 在默认情况下是阻塞的 

将fd设置为非阻塞:

// 设置非阻塞
int setfd_nonblock(int fd)
{
    int flag = fcntl(fd, cmd: F_GETFL, 0);
    return fcntl(fd, cmd: F_SETFL, flag | O_NONBLOCK);
}

// or

// 设置非阻塞
int SetFdNonblock(int fd) 
{
    assert(fd > 0);
    return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
}

而reactor模型使用的是非阻塞io。 

3.io多路复用

在计算机网络里面,有很多关于“复用”的用法,比如多路复用,意思就是本来一条链路上一次只能传输一个数据流,如果要实现两个源之间多条数据流同时传输,那就得需要多条链路了,但是复用技术可以通过将一条链路划分频率,或者划分传输的时间,使得一条链路上可以同时传输多条数据流。套用到I/O复用模型上,可以对应到如下应用场景:如果一个进程需要等到多种不同的消息,那么一般的做法就是开启多条线程,每个线程接收一类消息,如果每个线程都是采用阻塞式I/O模型,那么每个线程在消息未产生的时候就会阻塞,也就是说在多线程中使用阻塞式I/O。I/O复用就是基于上述的场景中,无需采用多线程监听消息的方式,进程直接监听所有的消息类型,这其中就涉及到select,poll,epoll,kqueue等不同的方法。

由此io多路复用的定义就诞生了

io多路复用(Input/Output Multiplexing)是一种在单个线程中管理多个输入/输出通道的技术。它允许一个线程同时监听多个输入流(例如网络套接字、文件描述符等),并在有数据可读或可写时进行相应的处理,而不需要为每个通道创建一个独立的线程。

4.同步io和异步io

阻塞式I/O、非阻塞式I/O、I/O复用模型是同步I/O模型,因为在等待数据的过程中,这三种模型中的进程都没有去做别的事情,即便是非阻塞式的轮询,也可以看作是一种同步。

POSIX将同步IO操作定义为“导致请求进程阻塞,直到I/O操作完成”,而书中认为在信号驱动式I/O模型中等待数据的那段时间不算是真正的I/O操作(因为没有调用I/O相关的系统调用),而数据从内核复制到用户空间才是真正的I/O操作(这个时候调用了recvfrom系统调用)。

而异步io首先用户态进程告诉内核态需要什么数据,然后用户态进程就不管了,做别的事情,内核等待用户态需要的数据准备好,然后将数据复制到用户空间,此时才告诉用户态进程,”数据都已经准备好,请查收“,然后用户态进程直接处理用户空间的数据。在复制数据到用户空间这个时间段内,用户态进程也是不阻塞的。

5.reactor模型解决问题的思路

 reactor是非阻塞同步网络模式,而proactor是异步网络模型。

reactor模型使用io多路复用去检测io事件是否就绪,如果有新然后用非阻塞io去操作具体的io事件。

它把对传统io的处理转化为了对事件的处理。对于服务端而言,我们并不知道客户端什么时候什么时候开始建立连接,传输数据和断开连接。reactor采用的方法是对一个未知接收连接的这件事感兴趣,先注册对这件事感兴趣,然后提供一个回调函数,未来当检测到事件就绪了,就主动调用这个回调函数。

reactor 模式主要由 reactor 和处理资源池这两个核心部分组成,它俩负责的事情如下:

1) reactor 负责监听和分发事件,事件类型包含连接事件、读写事件;

2) 处理资源池负责处理事件,如 read -> 业务逻辑 -> send;

reactor可以有一个,也可以有多个。同样的处理资源池也可以是单进程,也可以是多线程。

这里只讨论 单reactor + 多线程 和 多reactor + 多线程 这两种方式

1)单reactor + 多线程实现

1. reactor通过select/poll/epoll(io多路复用技术) 注册事件结点挂载到红黑树上,收到事件后通过 dispatch 进行分发,具体分发给 acceptor 对象还是 handler 对象,还要看收到的事件类型

2.如果是连接建立的事件,则交由 acceptor 对象进行处理,acceptor 对象会通过 accept 方法获取连接,并创建一个 handler 对象来处理后续的响应事件

3.如果不是连接建立事件, 则交由当前连接对应的 handler 对象来进行响应

4.handler 对象不再负责业务处理,只负责数据的接收和发送,handler 对象通过 read 读取到数据后,会从线程池中拉出一个空闲的子线程来处理数据

5.子线程里的 processor 对象就进行业务处理,处理完后,将结果发给主线程中的 handler 对象,接着由handler 通过 send 方法将响应结果发送给 client;

单reactor + 多线程 实现能够更加充分的利用cpu,提高资源利用的效率,但是同时也会引起由于多线程带来的资源竞争问题。

所以当多线程访问共享资源的时候,我们可以采取定义原子变量(atomic)和使用互斥锁(mutex)的方法来防止多线程引起的资源竞争问题。

2)多reactor + 多线程实现

1.主线程中的 mainreactor 对象通过 select/poll/epoll 监控连接建立事件,收到事件后通过 acceptor 对象中的accept 获取连接,将新的连接分配给某个子线程

2.子线程中的 subreactor 对象将 mainreactor 对象分配的连接加入select 继续进行监听,并创建一个handler 用于处理连接的响应事件

3.如果有新的事件发生时,subreactor 对象会调用当前连接对应的 handler 对象来进行响应

4.handler 对象通过 read -> 业务处理 -> send 的流程来完成完整的业务流程。

在多reactor + 多线程模式中 

主线程只负责接收新连接,子线程负责完成后续的业务处理。

主线程只需要把新连接传给子线程,子线程无须返回数据,直接就可以在子线程将处理结果发送给客户端。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值