文档章节

服务器高并发设计模式

满小茂
 满小茂
发布于 2016/04/13 23:17
字数 1670
阅读 223
收藏 3

半同步/半异步模式

先解释一下同步和异步的区别,与刚才I/O的同步、异步不一样,在并发模式中,这里的“同步"指的是程序完全按照代码的顺序执行,“异步”指的是程序的执行需要由系统事件来驱动,比如说信号、中断等。下图就清楚的解释了同步和异步操作的过程:

两种高效的事件处理模式和并发模式
 

这样看来,显然异步线程的执行效率高,但是它的编写相对复杂,难于调试,然而同步线程刚好相反,逻辑简单,但效率较差。半同步/半异步模式就结合了同步线程与异步线程的优点,它在处理I/O事件时使用异步线程,处理客户逻辑则使用同步线程。这样既满足了客户连接的实时性,又能同时处理多个连接。那么它是如何同将同步与异步结合起来的?实现半同步/半异步模式需要三个模块:异步处理模块、同步处理模块和队列模块

举个例子:

"一家律师事务所有一个前台接待员,每一位想寻找律师的客户,都会先由接待员接待,接待员会给每位顾客都安排一个律师来处理客户的案件,(假设一个律师在同一时间只能处理一个客户的案子)接待员只有一个人,但他可以接待所有客户,不过它也只负责接待,哪怕你的案件再复杂,都是律师的事儿,跟接待员没关系,而分配的依据可以是预约情况或者案件类型。"

在上面这个例子中,那个前台接待员就是异步处理模块,他一个人要处理多个I/O请求(客户),律师则是同步处理模块,每一个律师分别对应一个客户,根据客户的不同需求作出处理,而要让异步模块与同步模块连接起来,就需要插入一个队列模块,它将接待完毕的客户排一个队,等那个律师有时间的时候就来这个队列里领走一个客户处理,当然,队列怎么排,分为几个队列,就看客户到达的时间或者需求来决定了。

 

在实际使用中,我们一般使用多路复用IO在主线程上监听客户端的连接,监听到新的客户请求后,就将其封装成请求对象,然后插入请求队列中,同时,有许多工作线程可以来读取并处理该请求对象,具体选择哪个工作线程来为新的客户进行处理,取决于请求队列的设计。在这个模式中,最可能被阻塞的操作放在同步模块中,这样不会影响到异步模块的处理,不同模块可以使用不同的同步策略,互不干扰,模块间通信则使用ipc实现,但这样也造成了在同步模块和异步模块之间使用队列模块传送数据的时候,由于数据拷贝和上下文切换导致的性能消耗。

 

 

 

半同步/半反应堆模式

        半同步/半反应堆模式其实是半同步/半异步模式的一种变体,其中异步线程只有一个,由主线程充当,如果有连接到来或事件发生,主线程就将该socket插入请求队列中,直到这里与半同步/半异步模式都是一样的,但是在半同步/半反应堆模式中,当有任务到来时,选择哪个工作线程不是由算法或时间设置好的,而是由所有的工作线程竞争来的,它们通过竞争(比如申请互斥锁)来获得任务的接管权,这样的竞争机制使得当前只有空闲的工作线程才能来竞争,自然的形成了资源平衡。

 

          上图中主线程插入的请求队列是就绪的连接socket,这说明图示的半同步/半反应堆模式采用的事件处理模式是Reactor模式。半同步/半反应堆模式也可以采用模拟Proactor的事件处理模式,也就是由主线程完成数据的读写。主线程一般会将应用程序数据与其他信息一起封装为一个任务对象,然后将其插入请求队列。工作线程可以直接处理,不用读写。 半同步/半反应堆模式因为也是主线程和工作线程共享任务队列,所以也会存在与半同步/半异步模式一样的问题,就是每次堆队列进行操作,都需要进行加锁,从而消耗cpu的时间。而且一个线程同一时间只能处理一个客户请求,如果队列中积累了很多任务,增加工作线程的话,工作线程的切换也会耗费大量cpu时间,这种问题有一种相对高效的解决方式:即在每个工作线程上也使用epoll_wait,这样每个工作线程都能处理多个客户连接了。

 

 

领导者/追随者模式

           领导者/追随者模式是指多个工作线程轮流监听、分发、处理事件的一种模式。在任意事件,程序都仅有一个领导者线程,它负责监听I/O事件。其他线程都是追随者,它们休眠在线程池中等待成为新的领导者。当领导者线程检测到I/O事件时,首先要从线程池中选出新的领导者线程,然后处理I/O事件。此时,新的领导者线程等待新的I/O事件,旧的领导者线程处理I/O事件,实现并发。

           领导者/追随者模式最大的优点在于,它是自己监听I/O事件并处理客户请求,也就是说从接收到处理都是在同一线程中完成,所以不需要在线程之间传递任何额外的数据,也不用在线程间同步对请求队列的访问。但是它也有明显的缺点,就是只支持一种事件源集合,所以导致它不能像上述那样让每个线程独立的管理多个客户连接。

 

© 著作权归作者所有

共有 人打赏支持
满小茂
粉丝 75
博文 120
码字总数 134867
作品 0
成都
程序员
私信 提问
设计模式学习笔记之-代理模式

代理模式中,客户不会直接调用目标对象而是通过一个代码对象,客户调用代理对象代理对象去调用目标对象,起到对象与对象间的隔离作用。有时候我么不想直接访问目标对象,有时候我们不能直接访...

申文波
03/05
0
0
PHP设计模式(一):简介及创建型模式

我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式。 一、设计模式简介 首先我们来认识一下什么是设计模式: 设计模式是一套被反复使用、容易被他人理解的、可靠的代码设...

juhenj
2014/05/15
228
2
【23种设计模式之一】单例设计模式(翻译)

引言: 这一系列文章,翻译自网络上的文章,不过中间会夹杂着个人的理解,非原创,不过中文应该算是原创。 下面介绍,使用设计模式的一些好处: 1、设计模式是已经在工业生产中使用的,用于解...

敲代码猥琐男
2015/01/13
0
2
1、单例模式

定义: 单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例。 特点: 1、单例类只...

晚天吹凉风
02/22
0
0
编程中的那些套路——关于适配器模式

该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 今天我们来谈谈适配器模式。 想象一个场景: 有一个类方法它部署在服务器上,专门负责大多数语言都通用的...

gzchen
08/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

layer

Layui Layer在open弹出层中异步加载数据和form表单radio、checkbox、select不渲染,不可点击的解决办法 layer 实现弹窗提交信息 function confirmUpdateAward(i) { layer.open({ ...

mickelfeng
55分钟前
0
0
Spring boot中如何获取profiles环境

  实现ApplicationContextAware @Componentpublic class QiNiuPropertiesConfig implements ApplicationContextAware { /// 获取当前环境public String getActiveProfile() { ret......

writeademo
今天
2
0
机器学习中的End-to-End到底是怎么回事?

简单讲就是,Input--->系统(这里指神经网络)--->Output(直接给出输入,NN神经网络就给出结果,一气喝成!!!) 借用一段对话:(http://dy.163.com/v2/article/detail/C3J6F2NJ0511AQHO....

火力全開
今天
2
0
maven多个模块只编译并且只打包指定的模块

在多module的maven项目中,如果每次打包整个工程显得有些冗余和笨重。 命令:mvn clean package install -pl 模块的名称 -am

lifes77
今天
0
0
eosjs中文手册【2.0】

访问地址:eosjs 2.0 中文手册 - 汇智网

汇智网教程
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部