(转)Web服务的各种并发模型,以及适用场景

传统互联网后端服务,也就是网站后端服务,采用的是多进程的方式来提升网站的并发服务能力。随着移动互联网的兴起,移动终端设备数量迅速增长,现已远远超过PC终端数量,相应的对Web后端服务的处理能力要求也越来越高。面对成千上万的终端设备同时发出的请求,使用多进程方式的Web服务越来越觉得吃力。进程的资源开销非常大,单台服务器能同时运行的进程数一般也就几百,这就限制了服务的并发处理能力。本文首先对现有的Web服务进行分类,然后讨论对于每种Web服务类型,适用的并发模型,以及各种编程语言对其支持程度。

一、Web服务类型

  • 网站服务特点:输出HTML页面,需要处理页面显示逻辑;并发要求较低,一般为几十到几百。通常的网站后端服务就是这种。
  • API服务特点:输出JSON/XML数据,无页面显示逻辑;并发要求较高,一般为几百到几千。Facebook和新浪微博开放平台提供的API服务就属于这类。
  • 实时服务特点:输出JSON/XML数据,无页面显示逻辑;使用长连接,实时推送数据到客户端;并发要求很高,一般会同时维持成千上万个链接。这类服务多用于在线聊天,以及手机消息实时推送。

二、Web服务并发模型

对于上面提到的几种Web服务类型,有下面几种并发模型可供选择,它们各自有其优缺点。

  • 多进程(Multi-Process)该并发模型是目前使用得最广泛的模型,各种语言基本都支持。每个进程一次处理一个请求,并发能力等于进程数。优点:并发模型简单,由操作系统负责调度,稳定健壮;易管理,相关进程管理工具齐全;隔离性好,进程之间不会互相影响;代码兼容性好,无需考虑线程安全问题;能有效利用多核CPU,实现并行计算。缺点:由于单个进程需要加载完整应用,内存消耗大;进程间的切换开销较大;并发能力受限于系统进程数,比较低;单个请求处理需要非常快,否则很容易达到并发上限。
    支持语言:PHP、Python、Ruby
  • 多线程(Multi-Thread)这种模型是Java和.Net的常用模型。在重量级的进程里启动多个轻量级的线程,一个线程处理一个请求,并发能力等于线程数。优点:多个线程间共享进程资源,内存消耗较低;线程间切换开销较小;并发能力较高;能有效利用多核CPU,实现并行计算。缺点:应用代码及其用到的库必须是线程安全的;对共享资源的操作需要加锁,容易产生死锁问题;对虚拟机的内存管理要求很高,容易出现内存泄漏。
    支持语言:Java、.Net
  • 多进程+多线程(Multi-Process+Multi-Thread)该模型的出现是由于脚本语言(Python、Ruby)中普遍存在的全局解释器锁(GIL),导致一个进程内的多个线程无法同时在CPU的多个核上运行。通过启动多个进程,然后在单个进程内启动多个线程,既能充分利用多核CPU的计算能力,又提高了并发能力。一般启动的进程数等于CPU核数。该模型结合了多进程和多线程模型的优缺点。
  • 事件驱动(Event I/O)该模型利用通常应用中I/O操作的时间远大于CPU计算时间,在某个请求处于I/O等待状态时,把CPU资源分配给其它请求,从而将原本串行的请求处理变成了交叉处理,提高了CPU使用率的同时也提高了并发能力。优点:极高的并发能力,单机可以处理上万的并发连接;内存消耗低,单进程单线程,无需保存场景;资源消耗低,没有场景切换开销。缺点:需要使用异步编程方式,代码不易编写,且难于维护;所用库必须为异步;不适合CPU密集型应用;只能在单核上运行,无法利用多核CPU计算能力。
    支持语言:Python、Ruby、Java、.Net、Node.js
  • 协程(Coroutine)协程模型本质上也是事件驱动,是对“事件驱动”模型的高级封装,通过“协程”降低异步编程的复杂性。协程存在于用户空间,操作系统并不原生支持,因此协程的调度需要应用自己来负责。除了编程方式使用常见的同步方式而不是异步之外,其优缺点跟“事情驱动”模型基本一致。支持语言:Ruby、Scala、Go、Lua原生支持,Python和Node.js通过第三库支持

总体来说,多进程、多线程模型适合网站服务这类CPU密集型的服务,而事件驱动、协程模型更适合API服务、实时服务这些I/O密集型服务。
参考文献:
1、Web并发模型粗浅探讨 by robbin
2、Goroutine背后的系统知识 by 少年振南
来源:http://www.jaggerwang.net/article/771

发布日期:
分类:Docs