Apache 的两种模式: prefork 模式和 worker 模式
prefork 模式使用多个子进程,每个子进程只有一个线程,每个进程在确定的时间只能维持一个连接。而 worker 模式使用多个子进程,每个子进程有多个线程。每个线程在某个确定的时间只能维持一个连接。
对这两者进行分析:
在大多数平台上, Prefork MPM 在效率上要比 Worker MPM 要高,但是内存使用大得多。 prefork 的无线程设计在某些情况下将比 worker 更有优势:能够使用那些没有处理好线程安全的第三方模块,并且对于那些线程调试困难的平台而言,他也更容易调试一些。
而常来说,在一个高流量的 HTTP 服务器上, Worker MPM 是个比较好的选择,因为 Worker MPM 的内存使用比 Prefork MPM 要低得多。但 worker MPM 也由不完善的地方,假如一个线程崩溃,整个进程就会连同其任何线程一起 " 死掉 ". 由于线程共享内存空间,所以一个程式在运行时必须被系统识别为 " 每 个线程都是安全的 " 。
我们来看一看 worker 模式下的有关配置和机制
先小结一下, Worker 模式有一个单独的控制进程(父进程),它负责建立子进程,而每一个子进程有多个线程,每个线程在确定时间内只能维持一个连接。其关系图如下:
对于这个模式,可以进行相应的配置,现在我们来看看可以如何配置:
1. ThreadLimit:
子进程可以拥有的线程数的上限,默认值为 64 。
每个子进程可以拥有多个线程,而可以拥有的数量却是固定的, ThreadLimit 用来表示子进程可以建立的线程(包含多个服务线程和多个监听线程,监听线程用来监听接入请求并将其传递给服务线程处理和应答。)
2. ThreadsPerChild:
每个子进程建立的常驻的执行线程数,默认为 25 。每个子进程建立时创建线程,而此时创建线程的数量是固定的,由 ThreadsPerChild 决定。 ThreadsPerChild < ThreadLimit ,会被自动修正。
3. StartServers :
服务器启动时建立的子进程数, Worker 模式的默认值是 3.
4. MinSpareThreads
最小空闲线程数,默认为 75 。
Apache 总是试图维持一个备用 (spare) 或是空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理。
父进程会去检测所有子进程中空闲线程的总数,并要将这个总数维持在 MinSpareThreads 和 MaxSpareThreads 所指定的范围内。如果总数小于 MinSpareThreads ,那么子进程将产生新的空闲线程。
5. MaxSpareThreads
最大空闲线程数,默认为 250. 如果空闲线程数大于这个值,子进程将杀死多余的空闲线程。这个值的范围可能会被 Apache 自动修正,所以一般没有必要去修改这个值。 Apache 修正的标准是: MaxSpareThreads > MinSpareThreads + ThreadsPerChild
6. ServerLimit
Apache 允许的子进程的数量。
7. MaxClients
允许并行处理的最大接入请求数量(最大线程数量),默认值为 400 。超出 MaxClients 限制的请求将进入等待队列, MaxClients < ServerLimit* ThreadsPerChild ,会被自动修正。
8. MaxRequestsPerChild
每个子进程在其生存期内允许伺服的最大请求数量,到达 MaxRequestsPerChild 的限制后,子进程将会结束。如果 MaxRequestsPerChild = 0 ,子进程永远不会结束。
将 MaxRequestsPerChild 配置成非零值有两个好处:能够防止 ( 偶然的 ) 内存泄漏无限进行,从而耗尽内存;给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。
硬限制: ServerLimi 和 ThreadLimit 。要想改变这个硬限制必须完全停止服务器然后再启动服务器 ( 直接重启是不行的 ) 。
使用 ServerLimit 和 ThreadLimit 时要特别当心。假如将 ServerLimit 和 ThreadLimit 配置成一个高出实际需要许多的值,将会有过多的共享内存被分配。当配置成超过系统的处理能力, Apache 可能无法启动,或系统将变得不稳定。