CHAPTER 3. 并发设计空间
一、循环、并发及反应式服务器
循环服务器在处理后续请求之前,会完整地处理每一个客户请求。因此,在处理一个请求时,循环服务器要么将其他请求排成队列,要么忽略它们。
循环服务器适合以下两种服务:
l 短期服务
l 不经常运行的服务
在内部,循环服务器常常在“单进程”地址空间中执行服务请求。
并发服务器同时处理多个客户请求。根据OS和硬件平台不同,并发式服务器在执行它的服务时,要么使用多线程,要么使用多进程。
并发服务器非常适合“I/O操作频繁”的服务和“执行时间会变化”的长周期服务。
反应式服务器几乎是同时处理多个请求——尽管所有处理实际上在一个线程中完成的。多线程尚未在OS平台上广泛普及之前,并发处理通常是通过“同步事件多路分离”策略来实现的:多个服务请求由一个“单线程进程”依次循环处理。
二、多进程与多线程
进程是一种OS实体,用以提供“执行程序指令”的环境。
每一个进程都管理某些资源,如虚拟内存,I/O句柄,信号处理等,并借助内存管理单元(MMU)硬件,防止自身遭受其他OS进程破坏。
创建进程:UNIX fork()
WIN32 CreateProcess()
线程是一组单独的指令序列,执行在进程的保护范围之内。
创建线程:UNIX pthread_create()
WIN32 CreateThread()
在并发式网络应用程序的实现中,如果多个操作在各自的“线程”中执行,而不是在各自的“进程”中执行,以下“开发”开销就得以降低。
l 线程创建与环境切换
和进程相比,线程维护的状态信息要少。例如,在一个进程中切换线程时,进程范围内的资源(如虚拟地址映射和缓存)不需要改变。
l 同步
在调度、执行一个应用程序线程时,核心模式和用户模式之间的切换可能不必要。而且,“进程内”同步不需要OS内核干预。“进程间”同步则更昂贵。
l 数据复制
线程可以通过“进程局部内存”共享信息,这具有以下优点:
(1) 较之通过“共享内存”或“本地IPC”机制进行进程间通信,通过“进程局部内存”通信往往更有效率;因为数据不需要通过内核来复制。
(2) 在“进程局部内存”中,使用C++对象将更为容易,因为类的虚函数表不会存在“内存局部”问题。
但是,使用“多线程”实现“并发式”应用程序,也存在以下局限性:
l 性能损失
l 健壮性降低
l 缺乏高精度的访问控制
三、进程/线程创建策略
急式创建策略:在服务器创建期间,会有一个或多个OS进程/线程预先创建。
这些“热启动”的执行资源形成了一个池(pool),它改善了响应时间,但也增加了“请求被处理之前启动服务”的开销。
随需创建策略:在“客户连接”或“数据请求”到来时创建新进程或线程。
优点:资源消耗降低。
缺点:由于创建进程/线程和启动服务时会带来开销,因而,这些策略会降低“重负载”服务器的性能和实时系统的确定性。
四、用户、核心及混合线程模型
调度是OS提供的主要机制,用来确保应用程序正确使用主机的CPU资源。
在“多线程”进程中,线程是“调度”和“执行”的单元。
线程所处的竞争范围有2种:
l 进程竞争范围:各个线程在同一进程中竞争“被调度的CPU时间”。
l 系统竞争范围:线程直接和“系统范围”内的其他线程竞争。
当今常见的操作系统中,一共实现了三种线程调度模型:
l N:1用户线程模型
l 1:1核心线程模型
l N:M混合线程模型
五、分时及实时调度级别
除了以上讲的“竞争范围”和“线程模型”之外,OS平台一般还会定义一些策略和优先级,用以进一步影响“调度”行为。
分时调度级别: 通用型的OS调度器着眼于传统的分时、交互式环境。
该调度器往往具有以下特征:
l 基于优先级 —— 具有最高优先级的可运行线程是下一个将被调度执行的线 程。
l 公平 —— 在分时调度器中,根据线程使用CPU的情况,线程的优先级会发生变化。
l 抢占 —— 如果一个低优先级线程正在执行,此时,一个较高优先级的线程转为可运行状态,那么,调度器会抢占低优先级线程,让高优先级线程执行。
l 时间片 —— 用于循环执行“具有相同优先级”的线程。
实时调度级别:在分时调度器级别中,线程的执行通常没有固定次序。提供“实时调度级别”,以限制“最坏情况”下调度“用户线程”或“核心线程”所需的时间。
该调度器支持以下两种策略或其一:
l 轮流 —— 根据一个时间量,指定一个线程被另一个“具有相同优先级”的实时线程抢占之前,能够运行的最长时间。
l 先进先出 —— 高优先级线程能根据需要长时间运行,直到它自愿放弃控制,或被另一个具有更高优先级的实时线程抢占。
如果一个OS同时支持“分时”和“实时”调度级别,则“实时”线程总是比任何“分时”线程都具有更高的运行优先级。
六、“基于任务”与“基于消息”的体系
并发体系是联系以下要素的纽带:
1. CPU —— 为应用程序代码提供执行环境;
2. “数据”和“控制”消息 —— 在一个或多个应用程序或网络设备之间发送和接收;
3. 执行任务的服务 —— 当消息到达、离开时,基于消息执行服务。
在一个网络应用程序中,并发体系是影响“环境切换”、“同步”、“调度”和“数据移动”的成本,从而影响程序性能的几大要素之一。
并发体系的规范类型有两种:
l 基于任务的并发体系:根据应用程序中的“服务功能单元”来组织多个CPU。在这一体系中,任务是主动的,任务中处理的消息是被动的。
例如:“生产者/消费者模式”
l 基于消息的并发体系:“从应用程序和网络设备接收到的消息”来组织CPU。在这一体系中,消息是主动的,任务是被动的。
例如:“一个请求一个线程”;“一个连接一个线程”;“线程池”