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

本文深入分析了半同步半异步模式和领导者/追随者模式在构建高性能网络服务器时的实践应用。通过引用经典书籍和权威文档,解释了这两种设计模式的基本概念,并提供了实现细节。半同步半异步模式通过结合异步和同步操作的优点,实现了高效的数据处理。领导者/追随者模式则通过类比现实生活中的管理场景,展示了如何合理分配任务和资源。文中还通过实例代码演示了这两种模式在实际开发中的应用,包括使用循环队列和多线程进行任务调度。

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

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

在网 上一份资料 中引用了一本貌似很经典的书 i�^|@"+ 里的比喻: 
1r4,XSk ”  
许多餐厅使用 �/3^Pjx 半同步/半异步 模式的变体。例如,餐厅常常雇佣一个领班负责迎接顾客,并在餐厅繁忙时留意给顾客安排桌位, 
`pYE[y+ 为等待就餐的顾客按序排队是必要的。领班由所有顾客“共享”,不能被任何特定顾客占用太多时间。当顾客在一张桌子入坐后, 
h.b+r~u 有一个侍应生专门为这张桌子服务。  
M9g1d7% “   
Ap,q ` S 按照另一份似乎比较权威的文档的描述,要实现半同步/半异步模式,需要实现三层:异步层、同步层、队列层。因为很多操作 
4+,*sn 采用异步方式会比较有效率(例如高效率的网络模型似乎都采用异步IO),但是异步操作的复杂度比较高,不利于编程。而同步 
b6$4Ul-. 操作相对之下编程要简单点。为了结合两者的优点,就提出了这个模式。而为了让异步层和同步层互相通信(模块间的通信),系 
)%1&/uN) 统需要加入一个通信队列。异步层将操作结果放入队列,同步层从队列里获取操作结果。   
<C2c" =b 回过头来看看我之前写的那个select网络模型代码,个人认为基本上算是一个半同步半异步模式的简单例子:Buffer相当于通信 
gS0,')w 队列,网络底层将数据写入Buffer,上层再同步地从该队列里获取出数据。这样看来似乎也没什么难度。 = =   
J#_/+G i 关于例子代码,直接引用iunknown给的:   
7UY(' Q[ //这就是一个典型的循环队列的定义,iget 是队列头,iput 是队列尾</STRONG>    
Z)b)v int clifd[MAXNCLI], iget, iput;     
!kjr> :)x int main( int argc, char * argv[] )    
6kmZ!9w0| {    
dcc%G7w   ......    
]R3pBC"Jv   int listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );    
1RUbY>K#U   ......    
>�Qbc(}w   iget = iput = 0;    
1b]PCNz   for( int i = 0; i < nthreads; i++ ) {    
    pthread_create( &tptr.thread_tid, NULL, &thread_main, (void*)i );   R_*D7|v  
  for( ; ; ) {   )PoI~km  
    connfd = accept( listenfd, cliaddr,, &clilen );   a4qpnr]0  
    clifd[ iput ] = connfd;     // 接受到的连接句柄放入队列</STRONG>   =28H^rK{  
    if( ++iput == MAXNCLI ) iput = 0;     w,#W&>+&  
  }   bme#G{[)Y  
}   /2V',0  
void * thread_main( void * arg )   &_9e g  
{   uQ+$Hzx�X  
  for( ; ; ) {   RA67w&  
    while( iget == iput ) pthread_cond_wait( ...... );   Fa^]/:  
    connfd = clifd[ iget ];     // 从队列中获得连接句柄</STRONG>   3_/d=ZI/  
    if( ++iget == MAXNCLI ) iget = 0;   ~h+3WuOv  
    ......   9Ua@-  
    web_child( connfd );   VvKH]>*  
    close( connfd );   24fWj?A|�^  
  }   I'wAgf6W  
K(^x)w r-:  
2 .领导者/追随者(Leader/Followers):    zoU./]#C  
同样,给出别人引用的比喻: {mDaK&]Oh  
&zR}jD>  
在日常生活 中,领导者/追随者模式用于管理 许多飞机场出租车候车台。在该用例中,出租车扮演“线程”角色,排在第一辆的出 :1iw_GhJf  
租车成为领导者,剩下的出租车成为追随者。同样,到达出租车候车台的乘客构成了必须被多路分解给出租车的事件,一般以先进 U;31}'b  
先出排序。一般来说,如果任何出租车可以为任何顾客服务,该场景就主要相当于非绑定句柄/线程关联。然而,如果仅仅是某些 p#&6Ed*V  
出租车可以为某些乘客服务,该场景就相当于绑定句柄/线程关联。 #wo_  
“   ^/!^#rO  
其实这个更简单,我记得<unix网络编程>中似乎提到过这个。总之有一种网络模型(connection-per-thread?)里,一个线程用于 /oI''O%M  
accept连接。当接收到一个新的连接时,这个线程就转为connection thread,而这个线程后面的线程则上升为accept线程。这里, e#AB0-f  
accept线程就相当于领导者线程,而其他线程则属于追随者线程。   t^YDCcvoQ  
iunknown 的例子代码:   Ft]sTA+C  
int listenfd;   Ug9o/I@}C  
int main( int argc, char * argv[] )   %~eZrG.  
{   =/q3;5[  
  ......   HezCRtxRcc  
  listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );   'SuYNA)  
  ......   =EIsqk^*  
  for( int i = 0; i < nthreads; i++ ){   wD*_S}]  
    pthread_create( &tptr.thread_tid, NULL, &thread_main, (void*)i );   8 2_3|T  
  }   > Y LwWU<X  
  ......   .vwOp*3/  
}   U JY`P4(  
void * thread_main( void * arg )   (l9U7^S"{K  
{   8la.N*  
  for( ; ; ){   R7( + ^%  
    ......   ey@y?X=  
    // 多个线程同时阻塞在这个 accept 调用上,依靠操作系统的队列</STRONG>   qdjRw#LS^q  
    connfd = accept( listenfd, cliaddr, &clilen );   GK2 IY  
    ......   +g@@|&B  
    web_child( connfd );   [yf2_{*0T  
    close( connfd );   D-8%lGS  
    ......   ;#G>q�o  
  }   Ra;e#)7X  
eOZA2 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值