服务器框架模型

根据服务器后台操作是否会被阻塞可以分为同步和异步两大类

同步模型

l  单进程同步模型: 服务器只有在处理完成前一个客户请求才能处理下一个请求,最简单的服务器设计模型,没有之一,性能基本取决于后台操作的耗时。

l  多进程同步(fork)模型:每来一个请求fork一个进程处理,优点是进程之间,地址空间互相独立,因此处理起来也非常简单,缺点就是fork系统资源消耗较大,进程之间共享资源不如多线程方便,在进程数量逐渐增多时,性能急剧下降

l  多线程同步模型:每来一个请求创建一个独立线程处理,相对于多进程fork模型,线程创建代价较小,不过缺点是多个线程共享同一个进程空间,除了要注意线程安全问题外,在涉及到共享资源时要处理竞争和同步。

l  进程及线程组合同步模型:初听起来感觉疯了,从程序可维护的角度来看,不是模式越简单越好吗?话虽如此,不过在一些场景下,比如webcgi进程,需要请求后台的多个数据,这些请求之间是互相独立的,基本上(或者说很容易做到)资源没有竞争和冲突,所以可以很简单的将这些会阻塞主进程的请求放在独立的线程中执行,然后同时发往多个后台处理,主进程同步等待(join)这些请求的结果,从而将原来依次请求造成的多次阻塞变成了一次阻塞。当然由于线程执行函数体的格式是固定的【比如posix线程是void *(*start_routine)(void*)boost线程是void process())】,所以需要将原来的同步请求函数进行一次包裹,boost的话可以用bind很简单的将普通函数包裹成函数对象,然后传入boost线程中。

l  进程及协程组合同步模型:同前述场景一样,该模型将串行的阻塞请求并行化也非常方便。协程跟线程一样,同样有独立的栈空间,不同的是该组合模型在系统执行层面始终只有一个执行体在执行,基本上不存在资源访问冲突的问题(除非几个协程阻塞后的操作,会修改访问同一个资源),所以设计也更加健壮。而与线程组合同步模型相比,缺点是在阻塞操作前,需要主动释放(yieldcpu,因此需要业务api的支持(如修改同步请求api在阻塞前yield)。

 

 

此外常用的做法还有预fork的进程池(线程池)模型,相对多进程(多线程)而言,优点是减少了进程(线程)的创建开销,而更多时候由于性能消耗在同步等待后台操作上,所以整体性能相对于单进程同步模型而言最多只是线性倍数关系的提升。

异步模型

异步模型,由于不需要等待后台操作完成,整体性能相对于同步模型而言有了质的飞跃,异步模型一般采用多路复用机制(selectepoll等)进行调度。

l  消息传递模型:所有的后台服务器不维护状态,状态以及业务数据都保存在请求包中在后台多个服务器之间传递,有点类似于路由获取过程,每个服务器都将请求解开进行处理,再将处理结果放回请求包,发往下一个服务器接着处理。这种方案的有点是所有的服务器设计都非常简单,缺点是请求包较大,增加了网络消耗,另外也要求所有业务服务器配合,这一定程度上限制了这种模型的使用范围(有点类似于业务组的概念了)

l  状态机方案,优点是系统开销非常小,内存中只需要保存session状态数据即可,缺点是扩展性较差,同时状态之间的跳转对于习惯单进程处理的人类来说,简直各种头疼。所以对于代码编写和维护人员的要求都比较高。比较好的设计是可以采用boostbind和函数对象,不过处理多个异步调用的时候,还是会各种费力。

l  协程(Coroutine),使用协程编写异步服务程序,对于正常人类思维来说简直是个大救星,编写异步程序基本像同步程序一样简单,至少代码看起来是那么回事。协程相对状态机的缺点是相对状态机要占用更多的资源(如每个协程有一个独立栈空间,不过这个比起进程和线程来说就小多了),这限制了同一时刻系统中协程的存在数量,限制了系统性能的进一步提升。

   n  S->A->B->C这种串行调用ABC等若干服务的时候,主程序使用select/epoll等多路复用机制进行协程调度,而服务调用方式跟同步调用方式完全一样,整个的过程非常简单易懂。

   n  如果ABC之间没有依赖关系,将三者并行起来也并不复杂,只要先创建一个协程L(作为协程组leader),然后由L再创建三个协程ABC,主程序调度LABC任何一个可读写时被调度),然后再由L调度到ABC。(个人测试使用的c协程库是pcl-1.12

总结

从程序的可维护性角度考虑,

1)对于一些请求量较小的业务,可以使用进程阻塞模型,进程间通信可以使用消息队列,数据共享使用共享内存,这样可以有针对性的共享资源,业务逻辑层和proxy接口层尽量避免使用线程模型,因为搞不清哪天依赖的业务api线程不安全,导致程序很难维护。

2)对于依赖多个后台数据,优先考虑可以使用进程及协程组合模型,提高请求等待的并发性。如果不能修改同步请求的api源码(以库的形式提供的)且api线程安全,可以使用进程及线程组合模型代替。

3)对于请求量较大的业务,采用异步模型,后台依赖复杂,可以考虑使用协程+多路复用机制,如果后台依赖服务支持,可以使用消息传递模型,如果后台依赖不复杂可以使用状态机。(注意协程栈开销较大,使用前需要评估系统容量)

4)对于基本不依赖其他服务,业务逻辑改动也比较少(比如最底层的数据层),可以采用线程模型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值