概述
对于网络服务器后端开发,为满足不同并发场景的须要,一般来说,不外乎几种常见的并发模型,除了一些教学场景罕用的单线程、多过程(线程)的服务器实现外,生产用的服务器,个别都会思考应用IO多路复用模型。
而常见的IO多路复用场景 ,能够设计得很简略,也能够设计得比较复杂,个别依据业务须要而定。本文总结了一些比拟常见的服务器并发模型,根本涵盖了 大部分业务场景 。在理论业务开发的技术选型时,可依据场景,选取一款稳固、牢靠的网络模型,还是非常要害的。
模型一: 单线程Accept(无IO复用 )
模型剖析
- 主线程main thread执行阻塞accept, 每次客户端connect连贯过去,main thread中accept响应并建设连贯
- 创立连贯胜利,失去connect fd套接字后,仍然在main thread串行解决套接字读写,并解决业务
- 在解决业务时,如果有新客户端connect过去,server无响应,直到以后socket全副业务处理完毕(完结while循环)
- 以后客户端处理完毕之后,敞开连贯,解决下一个客户端申请
优缺点
长处
- socket编程流程清晰且简略,适宜学习应用,理解socket根本编程流程
毛病
- 该模型并非并发模型 ,是串行服务器,同一时刻,监听并响应的最大网络申请量为1, 即并发量为1
- 仅适学习根本socket编程,不适宜任何服务器server构建
模型二: 单线程 Accept + 多线程读写业务(无 IO 复用)
模型剖析
- 主线程main thread阻塞在accept, 每次客户端 connect连贯过去,main thread中accept响应并建设连贯
- 创立连贯胜利,失去connect fd套接字后,创立一个新的线程thread来解决客户端的读写业务,mian thread仍然回到accept阻塞期待新客户端
- thread通过套接字connect fd与客户端进行读写操作
- server在解决业务时,如果有新的客户端连贯过去,main thread中accept仍然能够响应并建设连贯,反复上述过程
优缺点
长处
- 基于模型1的优化,反对了并发的个性
- 应用比拟灵便,一个客户端对应一个线程独自解决,server解决业务的内聚性比拟高, 客户端无论如何读写 ,服务端 均会有一个 线程做资源响应
毛病
- 随着客户端梳理增多,须要开拓的线程数量也减少了,和server线程的数量是1:1的关系,因而对于高并发场景,线程数量受到硬件的瓶颈,线程过多也会 减少CPU的切换老本,升高CPU利用率
- 对于长连贯,客户端一旦无业务读写,只有不敞开,server就应该对放弃这个连贯的状态(心跳查看,健康检查机制),占用连贯资源和线程的开销
- 仅适宜客户端数量不大的场景,且可控的场景来应用
- 该模型仅适宜学习根本的socket编程,不适宜做并发服务器
模型三: 单线程多路IO复用
模型剖析
- 主线程main thread创立listen fd之后,采纳多路IO复用机制(如select、epoll)进行IO状态阻塞监控,有client连贯申请,IO 复用机制检测到listen fd触发读事件,则进行accept建设连贯,并将新生成的connect fd退出到监听IO汇合中
- client再次进行失常读写业务申请,main thread的多路IO复用机制阻塞返回,会触发该套接字 的读写事件等
- 对于client的读写业务,server仍然在main thread执行流程继续执行 ,此时如果有新的客户端connect申请过去,server将没有即时响应
- 等到server解决完一个连贯的读写操作,持续回到多路IO复用机制阻塞,其余连贯过去才能够失常执行
优缺点
长处
- 单流程体解决了能够同时监听多个客户端读写状态模型,不须要1:1客户端的线程数量关系
- 多路IO复用机制 是阻塞的,非忙轮询的状态,不会节约CPU资源,对CPU的利用率较高
- 对于连接数较多,然而并发不大的场景,或对实时性没有特地严格的场景,该模型曾经足够应用
毛病
- 尽管能够监听读个客户端的读写状态,然而同一时间内,只可能解决一个客户端的读写操作,实际上读写业务并发为1
- 当多个客户端拜访server,业务是串行执行,大量申请的会有排队提早景象。
模型四:单线程多路IO复用 + 多线程读写业务 (业务工作池)
模型剖析
- 主线程main thread 创立listen fd后,采纳多路IO复用机制(如select、epoll)进行IO状态阻塞监控,有client客户端connect申请 ,IO复用机制检测到listenfd触发读事件,则进行accept建设连贯,并将新生成的connect fd退出到监听IO汇合中
- 当connect fd有 可读音讯,触发读工夫,并进行读写音讯
- main thread依照固定协定读取音讯,并且交给worker pool工作线程池,工作线程池在server启动之前就曾经开启固定数量的thread,外面的线程只解决音讯 业务,不进行套接字读写操作
- 工作池解决完业务,触发connect fd写事件,将回执客户端的音讯通过main thread写给对方
- 即:main thread只解决IO阻塞监听以及具体的读写操作,读写到的数据交给具体的线程池解决,让main thread专一于解决IO事件
- 相似于Redis的解决机制
优缺点
长处
- 将业务解决的局部,通过工作池分离出来,可能缩小客户端拜访server导致业务串行执行会有大量申请排队的延迟时间
- 实际上读写的业务并发为1,然而业务流程的并发为线程池数量,放慢了业务解决的并行效率
毛病
- 读写仍然是main thread独自解决,最高的读写并行通道仍然是1
- 尽管多个worker thread解决业务,最初返回给client仍旧也须要排队,因为进口还是main thread的一个通道
模型五:单线程IO复用 + 多线程IO复用
模型剖析
- server在 启动监听前,开拓固定数量 (N)的 线程,用thread poll线程池治理
- 主线程main thread创立listen fd之后,采纳IO多路复用机制(如select、epoll)进行IO状态阻塞监控 ,有 client 连贯申请,IO复用机制 检测到listen fd触发读事件,则进行accept建设连贯 ,并将新生成的connect fd分发给thread pool中的某个线程进行监听
- thread pool中的每个thread都启动IO多路复用机制 ,用来监听main thread建设胜利并且散发下来的connect fd的读写事件,解决对应的读写业务,并将解决完的后果通过该thread本人的IO多路复用机制回执给客户端
优缺点
长处
- 将之前的main thread单流程的读写,扩散到多线程来实现,这样就减少了同一时刻 读写的并行通道,并行通道的数量N,N 就是线程池的数量
- server同时监听connect fd的数量,简直是成倍增加,之前的全副监控数量取决于main thread的多路IO复用机制的最大限度,所以实践上单点server最高响应并发数量应该是之前的N倍(N是 线程池数量,倡议线程数量和 CPU外围数1:1)
- 如果良好的 线程池数量可CPU外围数适配,那么能够尝试将CPU 与thread绑定,从而升高CPU的切换频率,进步每个thread解决正当业务的效率,升高CPU的切换老本
- memchached的并发模型与该模型比拟相似
毛病
- 尽管监听的并发数量晋升,然而最高的读写并行通道仍然为N,并且多个身处于同一个thread的客户端,会呈现读写排队景象,实际上每个thread模型与单线程IO多路复用机制是统一的
模型六: 单过程IO 复用 + 多过程IO复用
模型剖析
- 与单线程IO复用+ 多线程IO 复用(线程池)无太大差别
-
不同点
- 过程和线程的内存布局不同,导致main process(主过程)不再进行accept操作,而是将accept过扩散到各个子过程中
- 过程的个性,资源独立,所以main process如果accept胜利的fd,其余过程无奈资源共享,所以须要各个过程自行accept创立连贯
- main process 只是监听listen fd的状态,一旦触发读事件(有新连贯申请),通过一些IPC (过程间通信,如信号、共享内存、管道等),让各自子过程process竞争accpet实现连贯建设,并各自监听
优缺点
- 与单线程IO复用+ 多线程IO 复用(线程池)无太大差别
-
不同点:
- 多过程内存资源空间占用略微大一些
- 多过程模型平安稳定性较强,这也是各自过程互不烦扰的特点导致
- 实际上每个子过程process都是一个单线程IO多路复用模型
模型七: 单线程IO复用+ 多线程IO复用+ 多线程
模型剖析
- server在启动监听之前,开拓固定数量(N)的线程,用thread pool线程池治理
- 主线程main thread创立listen fd之后,采纳IO多路复用机制(如select、epoll)进行IO状态阻塞监控 ,有 client 连贯申请,IO复用机制 检测到listen fd触发读事件,则进行accept建设连贯 ,并将新生成的connect fd分发给thread pool中的某个线程进行监听
- thread pool中的每个thread都启动IO多路复用机制 ,用来监听main thread建设胜利并且散发下来的connect fd的读写事件,一旦有某个connect fd的读写事件被触发,立刻开拓一个新的 线程开解决IO读写业务
- 当某个线程解决完以后的读写业务,如果以后connect fd没有被敞开,那么将以后fd从新加回到thread pool的IO复用汇合,并将本身线程销毁
优缺点
长处
- 除了可能保障同时响应最高的并发数,又可能解决读写并行通道的局限问题
- 同一时刻读写并行通道,达到最大化极限,一个客户端能够对应一个独自的执行流程解决读写业务
毛病
- 该模型过于理想化,要求CPU外围数足够大
- 如果硬件CPU数量无限,那么该模型就造成大量CPU切换的老本节约。
- 理论开发中,简直用不到如此简单的网络模型,以后风行的开源网络组件中,也没有哪一款软件做到了如此简单的水平
本专栏知识点是通过<零声教育>的零碎学习,进行梳理总结写下文章,对C/C++课程感兴趣的读者,能够点击链接,查看具体的服务:C/C++Linux服务器开发/高级架构师