多线程Reactor分析,从性能,客户接入量方向

一. 为什么要使用Reactor设计模式 并发编程的最初模型 — 多线程阻塞IO模型 解决阻塞IO…

一. 为什么要使用Reactor设计模式

并发编程的最初模型 — 多线程阻塞IO模型

解决阻塞IO + 多线程资源浪费 — Reactor模型

二.Reactor线程模型分类

根据Reactor的数量和处理资源的线程数量的不同,分为三类:

单Reactor单线程模型

单Reactor多线程模型

多Reactor多线程模型

三.Reactor线程模型生活化

四. 总结本章

  • 前文精彩回顾,基于epoll封装一个简单的reactor反应堆模式, 事件循环
  • 并发编程的最初模型 — 多线程阻塞IO模型

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5p2wMzEy,size_20,color_FFFFFF,t_70,g_se,x_16

  • 缺点1: 每一个connect 都对应一个线程,线程占用系统资源,并发数过大时,系统资源不足以支撑. (系统资源上限制并发量)
  • 缺点2: 阻塞IO,在等待IO到来的时候会阻塞住线程,阻塞占用线程, 线程利用率低下,且线程数量有限,是对资源的一种极大的浪费 (占着线程不工作)
  • 解决阻塞IO + 多线程资源浪费 — Reactor模型

  1. 基于池化思想,避免为每个连接创建线程,连接完成后将业务处理交给线程池处理. (开启work_threads线程池处理业务需求) — 实现网络IO 跟 业务处理的解耦合 同时避免为每一个连接创建线程
  2. 基于IO复用技术,多个连接阻塞在同一个对象上,多个连接中出现IO事件的触发,操作系统就会通知应用程序处理 — 还是阻塞, 但是是多个IO阻塞在一个对象上, 所以多路:就是多个IO,复用 :复用一个线程
  • 理解IO复用:对比一下普通阻塞IO: 一个IO事件单独阻塞一个线程, 多路IO复用: 多个IO事件共同阻塞一个线程 — 将多个IO阻塞等待 重合阻塞在一起。提高线程利用率.

Reactor : 集合IO复用 + 线程池 思想. IO驱动—> 事件驱动 (事件循环)

根据Reactor的数量和处理资源的线程数量的不同,分为三类:

  • 单Reactor单线程模型

在一个Reactor中完成所有事情, IO事件注册,IO事件分发 IO事件处理 — 单个线程中实现

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5p2wMzEy,size_20,color_FFFFFF,t_70,g_se,x_16

缺陷:

  1. 单个线程处理所有请求, 对于多核CPU着实是一种浪费
  2. 当处理读写任务的线程负载过高后,处理速度下降,事件会堆积,严重的会超时,可能导致客户端重新发送请求,性能越来越差
  3. 不能支持高接入量, 服务器的接入量低, 因为在 accept 建立连接的请求中夹杂了大量的业务处理,业务处理耗时长, 造成accept占比低下,能同时支持的用户接入量低下

典型代表实例:redis 内存数据库 操作redis当中的数据结构

  • 单Reactor多线程模型

和单Reactor单线程相比核心在于将业务逻辑从Reactor中剥离出来放入work_threads中进行处理,实现网络IO 和 业务处理之间的解耦合。 充分利用多核资源,提高性能, 提高了用户接入量和可靠性

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5p2wMzEy,size_20,color_FFFFFF,t_70,g_se,x_16

缺陷:

Reactor线程承担所有的事件,既要处理新连接的建立,又要处理read, send IO事件, 高并发场景下单线程存在性能问题,并且对于高接入量场景下无法及时响应大量的acceptor.

代表:skynet

  • 多Reactor多线程模型

这种模型下和第二种模型相比是把Reactor线程拆分了mainReactor和subReactor两个部分,mainReactor只处理连接事件,读写事件交给subReactor来处理。业务逻辑还是由线程池来处理.

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5p2wMzEy,size_20,color_FFFFFF,t_70,g_se,x_16

mainRactor只处理连接事件,用一个线程来处理就好。处理读写事件的subReactor个数一般和CPU数量相等,一个subReactor对应一个线程,业务逻辑由线程池处理 (单独的main线程 mainReactor 专门处理连接, 可以大大的提高接入量 ) 可靠性大大提高

这种模型使各个模块职责单一,降低耦合度,性能和稳定性都有提高

这种模型在许多项目中广泛应用,比如Netty的主从线程模型 memcached 等

餐厅一般有接待员和服务员,接待员负责在门口接待顾客,服务员负责全程服务顾客

Reactor的三种线程模型可以用接待员和服务员类比

  1. 单Reactor单线程模型:接待员和服务员是同一个人,一直为顾客服务。客流量较少适合

  2. 单Reactor多线程模型:一个接待员,多个服务员。客流量大,一个人忙不过来,由专门的接待员在门口接待顾客,然后安排好桌子后,由一个服务员一直服务,一般每个服务员负责一片中的几张桌子

  3. 多Reactor多线程模型:多个接待员,多个服务员。这种就是客流量太大了,一个接待员忙不过来了

  • 本章从为传统的并发服务器:多线程阻塞IO 的弊端入手引出来为什么需要Reactor模式
  • 多线程阻塞IO : 主要弊端是:可以创建的线程量有限 — 并发量限制
  • 阻塞IO : 阻塞线程,线程的利用率有限 — 线程利用率不高
  • 线程池: 解决线程创建数量有限的问题, 复用线程 (网络IO 业务逻辑解除耦合性,避免一个连接创建一个线程)
  • IO复用技术:解决大量线程阻塞线程利用率不高的弊端.
  • 单个Reactor 单个线程处理网络IO连接 读写操作 + 业务逻辑. 网络模型不稳定,超高并发情况下不可靠,不能及时处理客户的连接请求等弊端,接入量低
  • 单Reactor + 多线程(线程池) 使用work_threads 来处理业务逻辑, 将网络IO和业务逻辑解除耦合性, 提高服务器面对高并发时候的稳定性, 可靠性, 但是对于突然的超多接入量情况下还是存在缺陷,因为Reactor 既处理acceptor 还处理 IO read write。而且也没有充分利用起来多核CPU的优势
  • 多Reactor + 线程池 模型,mainReactor仅仅只是处理 acceptor 连接, subReactor来处理 IO read write 操作. 大大提高了接入量 + 大大提高服务器的稳定新 和 可靠性,各个模块之间低耦合 且职责单一,更符合设计模式的要求
本文来自网络,不代表软粉网立场,转载请注明出处:https://www.rfff.net/p/6056.html

作者: HUI

发表评论

您的电子邮箱地址不会被公开。

返回顶部