Reactor模型

本文详细介绍了处理web请求的两种主要体系结构——基于线程和事件驱动,以及传统BIO通信的单线程和多线程模型的优缺点。接着,重点讲解了Reactor模型,包括单Reactor单线程、单Reactor多线程和主从Reactor多线程三种模式,分析了各自的适用场景和性能瓶颈。最后,提到了Netty和Kafka采用的主从Reactor多线程模型,强调了其在高并发处理中的优势。
摘要由CSDN通过智能技术生成

一、引言

在处理web请求时,通常有两种体系结构,分别为:thread-based architecture(基于线程)、event-driven architecture(事件驱动)。我们来看看他们具体是怎么实现的。

二、传统的BIO通信

1.单线程阻塞模型

  • 客户端向服务器端发出请求后,客户端会一直等待(不会再做其他事情),直到服务器端返回结果或者网络出现问题。

  • 服务器端同样的,当在处理某个客户端A发来的请求时,另一个客户端B发来的请求会等待,直到服务器端的这个处理线程完成上一个处理。

屏幕截图 2022-05-13 095514

缺点服务端一次只能同时处理一个客户端连接。因此这种模型是无法用于高并发服务器的。

2.多线程阻塞模型

既然服务端要处理多个请求,那直接增加线程数不就好了?

要知道多线程是有以下局限性的:

  • 虽然请求的处理交给了一个独立线程进行,但是操作系统通知accept()的方式还是单个的。也就是,服务器接收到数据报文后的“业务处理过程”可以多线程,但是数据报文的接受还是需要一个一个的来。(服务端对每个新连接都单独起一个线程去处理,主线程继续阻塞在accept上等待新连接。)
  • 系统最大线程数是有限的。如果创建过多的线程,可能会导致效率低下。
  • 线程的频繁切换也极度浪费系统资源。

这两种模型存在一些共同的问题:

  • 主线程每次调用 accept 函数获取客户端连接是阻塞的。必须要等待能获取到新连接之后,accept函数才会返回,否则主线程一直阻塞在accept上。
  • 子线程分配到新的客户端连接后,read和write操作也是阻塞的,导致白白地浪费线程资源。
  • 不利于同时多个socketfd的处理。

三、Reactor模型

Reactor线程模型就是多路I/O复用结合线程池的思想。

多个连接共用一个阻塞对象,应用程序无需阻塞等待所有连接,当某个连接有新的数据可以处理时,操作系统通知应用程序线程从阻塞状态返回,并将数据分发给对应的线程处理。

1.单Reactor单线程模式 (Reactor和handler都在同一个线程中)

  • select是IO复用模型介绍的标准网络编程API,可以实现应用程序通过一个阻塞对象监听多路连接请求。

  • Reactor对象通过Select监控客户端请求事件,收到事件后通过Dispatch进行分发。

  • 如果是建立连接请求事件,则由Acceptor通过Accept处理连接请求,然后创建一个Handler对象处理连接完成后的后续业务。

  • 如果不是建立连接事件,则Reactor会分发调用连接对应的Handler来处理业务。

  • Handler会完成Read->业务处理->Send的完整业务流程。

image-20220513102205288

缺点:

  • 服务器端用一个线程通过多路复用搞定所有的IO操作,包括连接、读、写等,但是如果客户端连接数较多,将无法支撑,比如处理一个客户端的业务时,别的客户端的业务请求只能阻塞等待
  • 单线程无法发挥多核CPU的性能。

2.单Reactor多线程

  • Reactor对象通过select监控客户端请求事件,收到事件后,通过dispatcher进行分发

  • 如果是建立连接的请求,则由Acceptor通过accept处理连接请求,然后创建一个Handler对象处理完成连接后的各种事件

  • 如果不是连接请求,则由Reactor分发调用连接对应的handler进行处理

  • handler只负责响应事件,不做具体的业务处理,通过read读取数据后,会分发给后面的worker线程池的某个线程处理业务

  • worker线程池会分发独立的线程完成真正的业务,并将结果返回给handler

  • handler收到响应的结果后,再通过send将结果返回给client

image-20220513102635708

缺点:

  • 一个reactor处理所有事件的监听和响应,在单线程运行,高并发场景下容易出现性能瓶颈

3.主从Reactor多线程

  • Reactor主线程MainReactor对象通过select监听连接事件,收到事件后,通过Acceptor处理连接事件

  • 当Acceptor处理连接事件后,MainReactor将连接分配给SubReactor

  • SubReactor将连接加入到连接队列进行监听,并创建handler进行各种事件处理

  • 当有新事件发生时,SubReactor就会调用对应的handler进行处理

  • handler通过Read读取数据,分发给后面的worker线程处理

  • worker线程池会分配独立的worker线程进行业务处理,并返回结果

  • handler收到响应的结果后,再通过send将结果返回给client

  • MainReactor主线程可以关联多个SubReactor子线程

image-20220513103046248

优点:

  • 主线程与子线程的数据交互简单职责明确,主线程只需要接收新连接,子线程完成后续的业务处理
  • 可以通过扩展多个Reactor子线程的方式来减小单个子线程的压力,提高并发处理能力

Netty和Kafka都采用了这种主从Reactor多线程的模型。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值