应用场景、池值确定、(IO bound/cpu bound)、线程池/进程池选择算法、负载均衡算法
概念
==进程池==:由服务器预先创建的一组子进程,子进程的数目在3~10个
之间(httpd守护进程使用7个子进程的进程池实现并发的,一般地线程池的线程数目应该与CPU的数量差不多)
引入的原因(动态创建子进程(或者子线程)来实现并发服务器的存在缺点)
- 动态创建进程(或线程)比较耗费时间,这将导致较慢的客户响应
- 动态创建的子进程通常只用来为一个客户服务,这样导致了系统上产生大量的细微进程(或线程)。进程和线程间的切换将消耗大量CPU时间
- 动态创建的子进程是当前进程的完整映像,当前进程必须谨慎的管理其分配的文件描述符和堆内存等系统资源,否则子进程可能复制这些资源,从而使系统的可用资源急剧下降,进而影响服务器的性能。
- 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务。
池子内什么时候装进程:并发的任务属于==计算密集型==
池子内什么时候装线程:并发的任务属于==IO密集型==
进程池中的子进程的特点
- 都运行着相同的代码,具有相同的属性,比如优先级,PGID(组识别码)等
- 进程池在服务器启动之初就创建好了,所以每个子进程都相对"干净",即它们没有打开不必要的文件描述符(从父进程继承而来)
- 也不会错误地使用大块的堆内存(从父进程复制得到)
新任务到来时,如何选择子进程?
- 使用某种算法(随机算法、Round Robin(轮流选择)),使任务在各个工作进程中更均匀地分配,从而减轻服务器的压力
- 主进程和所有子进程通过一个共享的工作队列来实现同步
:子进程都睡眠在该工作队列上,当有新的任务到来时,主进程将任务添加到工作队列中。这将唤醒正在等待任务的子进程,不过只有一个子进程将获得新任务的“接管权”,它可以从工作队列中取出任务并执行之,而其他子进程将继续睡眠在工作队列上。 - 主进程除了选择好子进程以外,还需要使用某种通知机制来告诉目标子进程有新任务需要处理,并传递必要的数据。
最简单的办法:在父子进程之间预先建立好一条管道,然后通过该管道来实现所有的进程间通信(预先定义好协议来规范管道的使用)(==父子线程间就可以直接用全局变量==)
处理多客户
监听socket和连接socket是否都由主进程来统一管理?
代码实现参考: