服务器动态创建子进程(或子线程)实现并发服务器缺点:
- 动态创建进程(或线程)是比较耗费时间的,这将导致较慢的客户响应。
- 动态创建的子进程(或子线程)通常只用来为一个客户服务(除非我们做特殊的处理),这将导致系统上产生大量的细微进(或线。进(或线)间的换将消耗大量 CPU 时间。
- 动态创建的子进程是当前进程的完整映像。当前进程必须谨慎地管理其分配的文件描述符和堆内存等系统资源,否则子进程可能复制这些资源,从而使系统的可用资源急剧下降,进而影响服务器的性能。
进程池和线程池可以解决上述问题。
进程池和线程池相似,所以这里只以进程池为例进行介绍。进程池是由服务器预先创建的一组子进程,这些子进程的数目在3-10个之间(当然, 这只是典型悄况)。httpd守护进程就是使用包含7个子进程的进程池来实现并发的。线程池中的线程数虽应该和CPU数盘差不多。
进程池中的所有子进程都运行相同的代码,并具有相同的属性,比如优先级、PGTD 等.因为进程池在服务器启动之初就创建好了,所以每个子进程都相对“干净”,即它们没 有打开不必要的文件描述符(从父进程继承而来),也不会错误地使用大块的堆内存(从父进程复制得到)。
当有新的任务到来时,主进程将通过某种方式选择进程池中的某一个子进程来为之服务。相比于动态创建子进程,选择一个已经存在的子进程的代价显然要小得多。
半同步/半异步进程池
为了避免在父、子进程之间传递文件描述符,将接受新连接的操作放到子进程中。对于这种模式来说,一个客户连接上的所有任务始终是由一个子进程在处理。
半同步/半反应堆线程池
相比于半同步/半异步进程池,半同步/半反应堆线程池的通用行要高得多,因为它使用一个工作队列完全解除了主线程和工作线程的耦合关系:主线程往工作队列中茶任务,工作线程通过竞争来获取任务并执行它。不过,如果要将该线程池应用到实际服务器程序中,那么要必须保证所有客户请求都是无状态的,因为同一个连接上的不同请求可能会由不同的线程处理。