当前位置: 首页 > Linux

源自生活的Reactor设计模式解析

时间:2023-04-07 01:04:10 Linux

1源自生活的设计模式我们生活中有一个地方,我们很舍不得去,但又不得不去医院。我们去医院看病需要走流程:第一步:挂号第二步:等叫号第三步:找到对应的医生,说出病情,医生会开化验单根据症状的化验单Step4:我们会带上化验单并使用仪器进行化验拿着化验报告去看医生。第六步:医生根据检查结果对症下药。大家都不愿意去医院,因为我们觉得去医院很麻烦。走完上面的流程,只需要一天的时间。在所有流程中,拨号和等待检测结果的等待时间最长。有些化验单可能要好几天才能出来,而且化验报告出来后,还需要排队等医生看化验结果。作为患者,我们希望到医院后能有一对一的服务,到医院后会有相应的医生全程跟进。但是如果我们作为医院的管理者,我们会怎么去思考这个问题,医院的医生和设备数量是有限的,但是每天的病人很多,基本上是医生的几十倍,如何利用有限的资源解决医生装备问题?还有更多耐心的问题呢?假设医院有10名医生和20台设备。医生执行步骤3需要10分钟,步骤6需要10分钟,设备执行步骤4需要20分钟,步骤5需要20分钟。如果医生在接诊后给患者开化验单,然后等病人拿到结果,给病人开药,然后送走,也就是医生跟着他从第3步到第6步,会很费时间。一个病人需要花费10+20+20+10=60分钟,一天8小时只能治疗8个病人,一个医院一天只能接诊108=80个病人。但是,如果在医生下完检测单后,即患者到下一个挂号患者处就诊,即执行完第3步后,医生可以继续拨打该号码并执行第2步,患者将拿到化验单后执行第5步后,就可以去找医生执行第6步了,这样资源就得到了充分的利用。医生看病人只需要能量。第3步和第6步没有,耗时10+10=20分钟,可以治疗860/20=24人,整个医院每天可以接诊10*24=240个病人。这就是Reactor设计模式的核心思想,解决了一对多的问题,大大提高了资源利用率。【文章福利】需要C/C++Linux服务器架构师学习资料加群1106747042(资料包括C/C++、Linux、golang技术、Nginx、ZeroMQ、MySQL、Redis、fastdfs、MongoDB、ZK、流媒体、CDN、P2P、K8S、Docker、TCP/IP、coroutines、DPDK、ffmpeg等)2Reactor设计模式实现NIO是一个非常经典的使用reactor设计模式的案例。当传统的IO客户端来一个连接时,服务端需要一个专门的线程来处理,每个线程都会完成一个交互操作,包括读取和返回。从表面上看,似乎连接不在线程中,但如果线程不够,新的连接将不会被处理。所以一个线程肩负着连接、读取、写入的责任。这种处理方式在海量并发的情况下,即使引入线程池也不能满足需求。这时候可以考虑把一个完整的请求分成几个小任务,就像医院把医生的会诊和仪器检查分开一样。每个Small任务都是非阻塞的,读写操作使用NIO。所以我们把一个连接操作拆分成多个任务,每个任务都是非阻塞的,这样大大提高了效率,但是线程池的线程数也会大大增加,但是线程更简单,任务单一,有点像我们的微服务思想。Reactor从线程池和Reactor的选择上可以细分为:Reactor单线程模型、Reactor多线程模型、Reactor主从模型。2.1Reactor单线程模型单线程模型使用专用线程来处理客户端请求。该线程循环监视客户端请求是否到达。一旦接收到客户端请求,就分发给相应的处理线程进行处理。该模式采用事件驱动设计,当事件触发时会调用处理器进行数据处理。Reactor模式可以控制线程的数量,一个线程可以处理大量的事件。2.2Reactor多线程模型采用一个线程支持所有IO处理,但瓶颈也很明显。如果客户端多次请求,在业务线程中处理缓慢,会导致后续客户端积压,导致响应缓慢,因此需要引入Reactor多线程模型。可以在线程池中引入工作线程,处理器的执行放在线程池中,使用多线程来处理业务逻辑。2.3Reactor主从模型对于多CPU的机器,为了充分利用系统资源,Reactor会被拆分成两部分。1)MainReactor负责监听连接,并将监听到的连接交给SubReactor处理,MainReactor用于响应连接请求。2)SubReactor处理连接,Reactor用于处理IO操作请求。3架构模型Handle:操作系统的句柄,可以是一个打开的文件,一个Socket连接,一个Timer定时器等SynchronousEventDemultiplexer:同步(多路)事件分离器,阻塞和等待Handles中的事件发生。InitiationDispatcher:初始的事件分发器,提供注册、删除、转发的方法EventHandlersEventHandler:事件处理程序的接口ConcreteEventHandler:事件处理程序的实际实现,绑定一个Handle。因为在实际情况中,我们往往会有多个事件处理程序,所以这里将事件处理程序的接口和实现分开,类似于C++、Java等高级语言中的多态。————————————————