半同步半异步模式以及Leader_Follwer模式

这里提到的两个设计模式都是用于高并发系统(例如一个高性能的网络服务器)的。这里我只是简单地提一下:    1. 半同步/半异步(half-sync/half-async ):

三、 半同步-半异步模型 http://www.cppblog.com/liangairan/articles/62917.html?opt=admin 1. 话说一个地方有一群有组织无纪律的人从事山贼这个很有前途的职业。 2. 他们有一个山贼头头,他专门负责望风,其他的喽罗待命。 3. 假如发现有落单的过往客商,山贼头头会到路口拦路,让客商双手抱头蹲在地上,然后让一个小喽罗为这个倒霉鬼"服务"。 4. 假如客商很多,山贼头头会让客商在地上蹲成一排(严肃点,排队啦,打劫啦)。 一群小喽罗挨个为大家"服务"。 5. 头头的工作很重要,对于每个客商他都不会花费太多时间,拦路以后,他会让客商排队等待打劫。 6. 过往客商太多而山贼数量不够,客商的排队可能需要等待较长的时间。

在网 上一份资料 中引用了一本貌似很经典的书 里的比喻:  ”   许多餐厅使用 半同步/半异步 模式的变体。例如,餐厅常常雇佣一个领班负责迎接顾客,并在餐厅繁忙时留意给顾客安排桌位,  为等待就餐的顾客按序排队是必要的。领班由所有顾客“共享”,不能被任何特定顾客占用太多时间。当顾客在一张桌子入坐后,  有一个侍应生专门为这张桌子服务。   “    按照另一份似乎比较权威的文档的描述,要实现半同步/半异步模式,需要实现三层:异步层、同步层、队列层。因为很多操作  采用异步方式会比较有效率(例如高效率的网络模型似乎都采用异步IO),但是异步操作的复杂度比较高,不利于编程。而同步  操作相对之下编程要简单点。为了结合两者的优点,就提出了这个模式。而为了让异步层和同步层互相通信(模块间的通信),系  统需要加入一个通信队列。异步层将操作结果放入队列,同步层从队列里获取操作结果。    回过头来看看我之前写的那个select网络模型代码,个人认为基本上算是一个半同步半异步模式的简单例子:Buffer相当于通信  队列,网络底层将数据写入Buffer,上层再同步地从该队列里获取出数据。这样看来似乎也没什么难度。 = =    关于例子代码,直接引用iunknown给的:    //这就是一个典型的循环队列的定义,iget 是队列头,iput 是队列尾</STRONG>     int clifd[MAXNCLI], iget, iput;      int main( int argc, char * argv[] )     {       ......       int listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );       ......       iget = iput = 0;       for( int i = 0; i < nthreads; i++ ) {         pthread_create( &tptr.thread_tid, NULL, &thread_main, (void*)i );       for( ; ; ) {         connfd = accept( listenfd, cliaddr,, &clilen );         clifd[ iput ] = connfd;     // 接受到的连接句柄放入队列</STRONG>         if( ++iput == MAXNCLI ) iput = 0;         }     }     void * thread_main( void * arg )     {       for( ; ; ) {         while( iget == iput ) pthread_cond_wait( ...... );         connfd = clifd[ iget ];     // 从队列中获得连接句柄</STRONG>         if( ++iget == MAXNCLI ) iget = 0;         ......         web_child( connfd );         close( connfd );       }     }   

http://blog.csdn.net/cjfeii/article/details/17267487

1.动机:

众所周知,同步模式编程简单,但是I/O的利用利率低;而异步模式编程复杂,但是I/O利用率高。 综合同步异步的有优点,就有了半同步半异步的设计模式。 这个模式中,高层使用同步I/O模型,简化编程。低层使用异步I/O模型,高效执行。

half sync/half async可以很好的使得"变成复杂度"和"执行效率"之间达到一种平衡.

2.应用场景:

半同步半异步模式在下面的场景中使用:

2.1 一个系统中的进程有下面的特征:

系统必须响应和处理外部异步发生的事件, 如果为每一个外部资源的事件分派一个独立的线程同步处理I/O,效率很低。 如果上层的任务以同步方式处理I/O,实现起来简单。

2.2 一个或多个任务必须在单独的控制线程中执行,其它任务可以在多线程中执行:

上层的任务(如:数据库查询,文件传输)使用同步I/O模型,简化了编写并行程序的难度。 而底层的任务(如网络控制器的中断处理)使用异步I/O模型,提供了执行效率。

一般情况下,上层的任务要比下层的任务多,使用一个简单的层次实现异步处理的复杂性,可以对外隐藏异步处理的细节。另外,同步层次和异步层次任务间的通信使用一个队列来协调。

3.实现方案:

可以分为三层:同步任务层,队列层,异步任务层。

3.1 同步任务层(用户级的进程):

本层的任务完成上层的I/O操作,使用同步I/O模型,通过队列层的队列中传输数据。和异步层不同,同步层的任务使用活动对象执行,这些活动对象有自己运行栈和寄存器状态。当执行同步I/O的时候,他们会被阻塞/睡眠。

3.2 队列层:

这个层在同步任务层和异步任务层之间,提供了同步控制和缓存的功能。异步任务的I/O 事件被缓存到消息队列中,同步任务层在队列中提取这些事件(相反方向亦然)

3.3 异步任务层:

处理低层的事件,这些事件由多个外部的事件源产生(例如网卡,终端)。和异步任务不同,此层的实体是被动对象,没有自己的运行栈,要求不能被阻塞。

4.优缺点:

4.1 半同步半异步模式有下面的优点:

上层的任务被简化 不同层可以使用不同的同步策略 层间的通信被限制在单独的一点,因为所有的交互使用队列层协调。 在多处理器环境中提高了性能。

4.2 半同步半异步模式有下面的缺点:

跨边界导致的性能消耗,这是因为同步控制,数据拷贝和上下文切换会过度地消耗资源。

上层任务缺少异步I/O的实现。

2 .领导者/追随者(Leader/Followers):

领导者-追随者模型 http://www.cppblog.com/liangairan/articles/62917.html?opt=admin 打比方: 1. 话说一个地方有一群有组织无纪律的人从事山贼这个很有前途的职业。 2. 一般就是有一个山贼在山路口察看,其他人在林子里面睡觉。 3. 假如发现有落单的过往客商,望风的山贼就会弄醒一个睡觉的山贼,然后自己去打劫。 4. 醒来的山贼接替作望风的事情。 5. 打劫的山贼搞定以后,就会去睡觉,直到被其他望风的山贼叫醒来望风为止。 6. 有时候过往客商太多,而山贼数量不够,有些客商就能侥幸平安通过山岭(所有山贼都去打劫其他客商了)。 计算机版本 1. 有若干个线程(一般组成线程池)用来处理大量的事件 2. 有一个线程作为领导者,等待事件的发生;其他的线程作为追随者,仅仅是睡眠。 3. 假如有事件需要处理,领导者会从追随者中指定一个新的领导者,自己去处理事件。 4. 唤醒的追随者作为新的领导者等待事件的发生。 5. 处理事件的线程处理完毕以后,就会成为追随者的一员,直到被唤醒成为领导者。 6. 假如需要处理的事件太多,而线程数量不够(能够动态创建线程处理另当别论),则有的事件可能会得不到处理。 同样,给出别人引用的比喻:   ”   在日常生活 中,领导者/追随者模式用于管理 许多飞机场出租车候车台。在该用例中,出租车扮演“线程”角色,排在第一辆的出   租车成为领导者,剩下的出租车成为追随者。同样,到达出租车候车台的乘客构成了必须被多路分解给出租车的事件,一般以先进   先出排序。一般来说,如果任何出租车可以为任何顾客服务,该场景就主要相当于非绑定句柄/线程关联。然而,如果仅仅是某些   出租车可以为某些乘客服务,该场景就相当于绑定句柄/线程关联。   “     其实这个更简单,我记得<unix网络编程>中似乎提到过这个。总之有一种网络模型(connection-per-thread?)里,一个线程用于   accept连接。当接收到一个新的连接时,这个线程就转为connection thread,而这个线程后面的线程则上升为accept线程。这里,   accept线程就相当于领导者线程,而其他线程则属于追随者线程。     iunknown 的例子代码:     int listenfd;     int main( int argc, char * argv[] )     {       ......       listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );       ......       for( int i = 0; i < nthreads; i++ ){         pthread_create( &tptr.thread_tid, NULL, &thread_main, (void*)i );       }       ......     }     void * thread_main( void * arg )     {       for( ; ; ){         ......         // 多个线程同时阻塞在这个 accept 调用上,依靠操作系统的队列</STRONG>         connfd = accept( listenfd, cliaddr, &clilen );         ......         web_child( connfd );         close( connfd );         ......       }     }  

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏FreeBuf

使用各种扫描工具的你,不但踩了“蜜罐”可能还要被团灭了

*本文原创作者:evil7,本文属FreeBuf原创奖励计划,未经许可禁止转载 ? 工作后,越来越没有时间挖洞和写东西了(被世俗的纷争与微弱的工资束缚着),真是...

30980
来自专栏IT大咖说

Elastic探秘:技术海洋里遗落的珍珠

内容来源:2018 年 06 月 30 日,Elastic工程师与布道师曾勇在“Elastic Meetup 南京交流会”进行的《Elastic探秘之遗落的珍珠...

11830
来自专栏大数据挖掘DT机器学习

QQ空间(日志、说说、个人信息)python爬虫源码(一天可抓取 400 万条数据)

爬虫功能: QQSpider 使用广度优先策略爬取QQ空间中的个人信息、日志、说说、好友四个方面的信息。 判重使用“内存位”判重,理论上亿数量级的QQ可瞬间判...

62940
来自专栏安富莱嵌入式技术分享

【专题教程第8期】基于emWin模拟器的USB BULK上位机开发,仅需C即可,简单易实现

说明: 1、如果你会emWin话的,就可以轻松制作上位机。做些通信和控制类上位机,比使用C#之类的方便程度一点不差,而且你仅会C语言就可以。 2、并且成功将em...

17920
来自专栏IT技术精选文摘

海量之道之弱联网优化

14740
来自专栏数据和云

从一个故障案例看强大到令人发紫的Oracle数据库--我和数据中心的故事

作为一名混迹数据库江湖十几年的老DBA,当你对关系型数据库的了解越来越深入时,你会发现,Oracle数据库真的是强大到令人发紫! Oracle数据库的强大,不仅...

33140
来自专栏数据之美

linux 系统监控、诊断工具之 IO wait

1、问题: 最近在做日志的实时同步,上线之前是做过单份线上日志压力测试的,消息队列和客户端、本机都没问题,但是没想到上了第二份日志之后,问题来了: 集群中的某台...

457100
来自专栏Crossin的编程教室

喜大普奔!Django官方文档终于出中文版了

之前对于 Django 的学习我一直推荐看官方文档,但不得不加上一句“如果你英语水平允许的话……”。现在总算是等来好日子了。各位想向网站/服务器开发方向进阶的同...

24610
来自专栏PPV课数据科学社区

QQ空间(日志、说说、个人信息)python爬虫源码(一天可抓取 400 万条数据)

爬虫功能: QQSpider 使用广度优先策略爬取QQ空间中的个人信息、日志、说说、好友四个方面的信息。 判重使用“内存位”判重,理论上亿数量级的QQ可瞬间判...

56950
来自专栏玉树芝兰

如何用Sikuli自动录入成绩?

手里明明有一份学生成绩Excel表格,却还得一一手动把它们输入到教务系统?类似这样的简单重复枯燥操作,其实你都可以一键让电脑自动替你完成。

22020

扫码关注云+社区

领取腾讯云代金券