标题：多路处理模块
简介
多路处理模块，Multi-Processing Modules，MPM
Apache是基于模块化的设计，而Apache 2.0更扩展了模块化设计到Web服务器的最基本功能。服务器装载了一种多路处理模块，负责绑定本机网络端口、接受请求，并调度子进程来处理请求。
ApacheHTTP服务器被设计为一个强大的、灵活的能够在多种平台以及不同环境下工作的服务器。不同的平台和不同的环境经常产生不同的需求，或是为了达到同样的最佳效果而采用不同的方法。Apache凭借它的模块化设计很好的适应了大量不同的环境。这一设计使得网站管理员能够在编译时和运行时凭借载入不同的模块来决定服务器的不同附加功能。  Apache2.0将这种模块化的设计延伸到了web服务器的基础功能上。这个版本带有多路处理模块(MPM)的选择以处理网络端口绑定、接受请求并指派子进程来处理这些请求。
将模块化设计延伸到这一层次主要有以下两大好处：
Apache可以更简洁、更有效地支持各种操作系统。尤其是在mpm_winnt中使用本地网络特性代替Apache1.3中使用的POSIX模拟层后，Windows版本的Apache现在具有更好的性能。这个优势借助特定的MPM同样延伸到了其他各种操作系统。
服务器可以为某些特定的站点进行定制。比如，需要更好伸缩性的站点可以选择象worker或event这样线程化的MPM，而需要更好的稳定性和兼容性以适应一些旧的软件的站点可以用prefork 。
从用户角度来看，MPM更像其他的Apache模块。主要的不同在于：不论何时，必须有且仅有一个MPM被载入到服务器中。现有的MPM列表可以在模块索引中找到。  
选择一个MPM
MPM必须在编译配置时进行选择，并静态编译到服务器中。如果编译器能够确定线程功能被启用，它将会负责优化大量功能。因为一些MPM在Unix上使用了线程，而另外一些没有使用，所以如果在编译配置时选择MPM并静态编译进Apache，Apache将会有更好的表现。
可以在使用configure脚本时用 --with-mpm=NAME 选项指定MPM，NAME就是想使用的MPM的名称。
一旦服务器编译完成，就可以用 ./httpd -l 命令来查看使用了哪个MPM。这个命令将列出所有已经被编译到服务器中的模块，包括MPM。
多路处理模块-默认的MPM

下表列出了不同操作系统上默认的MPM。如果你在编译时没有进行选择，这将是默认选择的MPM。
BeOS beosNetwarempm_netwareOS/2mpmt_os2UnixpreforkWindowsmpm_winnt
MPM模块简介
beos 专门针对BeOS优化过的多路处理模块(MPM) 
event 一个标准workerMPM的实验性变种。 
mpm_netware Novell NetWare优化过的线程化的多路处理模块(MPM) 
mpmt_os2 专门针对OS/2优化过的混合多进程多线程多路处理模块(MPM) 
prefork 一个非线程型的、预派生的MPM 
mpm_winnt 用于Windows NT/windows 2000/Windows XP/windows 2003 系列的MPM 
worker 线程型的MPM，实现了一个混合的多线程多处理MPM，允许一个子进程中包含多个线程。
Apache MPM prefork
Preforking MPM 概述

-Apache MPM worker
worker mpm
支持混合的多线程多进程的多路处理模块
概述
此多路处理模块(MPM)使网络服务器支持混合的多线程多进程。由于使用线程来处理请求，所以可以处理海量请求，而系统资源的开销小于基于进程的MPM。但是，它也使用了多进程，每个进程又有多个线程，以获得基于进程的MPM的稳定性。
控制这个MPM的最重要的指令是，控制每个子进程允许建立的线程数的ThreadsPerChild指令，和控制允许建立的总线程数的MaxClients指令。
工作方式
每个进程可以拥有的线程数量是固定的。服务器会根据负载情况增加或减少进程数量。一个单独的控制进程(父进程)负责子进程的建立。每个子进程可以建立ThreadsPerChild数量的服务线程和一个监听线程，该监听线程监听接入请求并将其传递给服务线程处理和应答。
Apache总是试图维持一个备用(spare)或是空闲的服务线程池。这样，客户端无须等待新线程或新进程的建立即可得到处理。初始化时建立的进程数量由StartServers指令决定。随后父进程检测所有子进程中空闲线程的总数，并新建或结束子进程使空闲线程的总数维持在MinSpareThreads和MaxSpareThreads所指定的范围内。由于这个过程是自动调整的，几乎没有必要修改这些指令的缺省值。可以并行处理的客户端的最大数量取决于MaxClients指令。活动子进程的最大数量取决于MaxClients除以ThreadsPerChild的值。
有两个指令设置了活动子进程数量和每个子进程中线程数量的硬限制。要想改变这个硬限制必须完全停止服务器然后再启动服务器(直接重启是不行的)，ServerLimit是活动子进程数量的硬限制，它必须大于或等于MaxClients除以ThreadsPerChild的值。ThreadLimit是所有服务线程总数的硬限制，它必须大于或等于ThreadsPerChild指令。这两个指令必须出现在其他workerMPM指令的前面。
在设置的活动子进程数量之外，还可能有额外的子进程处于"正在中止"的状态但是其中至少有一个服务线程仍然在处理客户端请求，直到到达MaxClients以致结束进程，虽然实际数量会很小。这个行为能够通过以下禁止特别的子进程中止的方法来避免：
* 将MaxRequestsPerChild设为"0"
* 将MaxSpareThreads和MaxClients设为相同的值
一个典型的针对workerMPM的配置如下：
ServerLimit 16
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
在Unix中，为了能够绑定80端口，父进程一般都是以root身份启动，随后，Apache以较低权限的用户建立子进程和线程。User和Group指令用于设置Apache子进程的权限。虽然子进程必须对其提供的内容拥有读权限，但应该尽可能给予它较少的特权。另外，除非使用了suexec ，否则，这些指令设置的权限将被CGI脚本所继承。
MaxRequestsPerChild指令用于控制服务器建立新进程和结束旧进程的频率。
MPM常用指令
StartServers 指令
StartServers指令设置了服务器启动时建立的子进程数量。
因为子进程数量动态的取决于负载的轻重，所有一般没有必要调整这个参数。
MinSpareServers 指令
MinSpareServers指令设置空闲子进程的最小数量。
所谓空闲子进程是指没有正在处理请求的子进程。如果当前空闲子进程数少于MinSpareServers ，那么Apache将以最大每秒一个的速度产生新的子进程。
只有在非常繁忙机器上才需要调整这个参数。将此参数设的太大通常是一个坏主意。
MaxSpareServers 指令
MaxSpareServers指令设置空闲子进程的最大数量。
所谓空闲子进程是指没有正在处理请求的子进程。如果当前有超过MaxSpareServers数量的空闲子进程，那么父进程将杀死多余的子进程。
只有在非常繁忙机器上才需要调整这个参数。将此参数设的太大通常是一个坏主意。如果将该指令的值设置为比MinSpareServers小，Apache将会自动将其修改成"MinSpareServers+1"。
MaxClients 指令
MaxClients指令设置了允许同时伺服的最大接入请求数量。
任何超过MaxClients限制的请求都将进入等候队列，直到达到ListenBacklog指令限制的最大值为止。一旦一个链接被释放，队列中的请求将得到服务。
对于非线程型的MPM(也就是prefork)，MaxClients表示可以用于伺服客户端请求的最大子进程数量，默认值是256。要增大这个值，必须同时增大ServerLimit 。
对于线程型或者混合型的MPM(也就是beos或worker)，MaxClients表示可以用于伺服客户端请求的最大线程数量。线程型的beos的默认值是50。对于混合型的MPM默认值是16(ServerLimit)乘以25(ThreadsPerChild)的结果。因此要将MaxClients增加到超过16个进程才能提供的时候，必须同时增加ServerLimit的值。
MaxRequestsPerChild 指令
MaxRequestsPerChild指令设置每个子进程在其生存期内允许伺服的最大请求数量。到达MaxRequestsPerChild的限制后，子进程将会结束。如果MaxRequestsPerChild为"0"，子进程将永远不会结束。
不同的默认值
在mpm_netware和mpm_winnt上的默认值是"0"。
将MaxRequestsPerChild设置成非零值有两个好处：
* 可以防止(偶然的)内存泄漏无限进行，从而耗尽内存。
* 给进程一个有限寿命，从而有助于当服务器负载减轻的时候减少活动进程的数量。
注意：
对于KeepAlive链接，只有第一个请求会被计数。事实上，它改变了每个子进程限制最大链接数量的行为。
ThreadsPerChild 指令
这个指令设置了每个子进程建立的线程数。
子进程在启动时建立这些线程后就不再建立新的线程了。如果使用一个类似于mpm_winnt只有一个子进程的MPM，这个数值要足够大，以便可以处理可能的请求高峰。如果使用一个类似于worker有多个子进程的MPM，每个子进程所拥有的所有线程的总数要足够大，以便可以处理可能的请求高峰。
对于mpm_winnt，ThreadsPerChild的默认值是64；对于其他MPM是25。
ThreadLimit 指令
这个指令设置了每个子进程可配置的线程数ThreadsPerChild上限。
任何在重启期间对这个指令的改变都将被忽略，但对ThreadsPerChild的修改却会生效。
使用这个指令时要特别当心。如果将ThreadLimit设置成一个高出ThreadsPerChild实际需要很多的值，将会有过多的共享内存被分配。如果将ThreadLimit和ThreadsPerChild设置成超过系统的处理能力，Apache可能无法启动，或者系统将变得不稳定。该指令的值应当和ThreadsPerChild可能达到的最大值保持一致。
对于mpm_winnt，ThreadLimit的默认值是1920；对于其他MPM这个值是64。
注意：
Apache在编译时内部有一个硬性的限制"ThreadLimit 20000"(对于mpm_winnt是"ThreadLimit 15000")，不能超越这个限制。
ServerLimit 指令
对于preforkMPM，这个指令设置了MaxClients最大允许配置的数值。
对于workerMPM，这个指令和ThreadLimit结合使用设置了MaxClients最大允许配置的数值。任何在重启期间对这个指令的改变都将被忽略，但对MaxClients的修改却会生效。
使用这个指令时要特别当心。如果将ServerLimit设置成一个高出实际需要许多的值，将会有过多的共享内存被分配。如果将ServerLimit和MaxClients设置成超过系统的处理能力，Apache可能无法启动，或者系统将变得不稳定。
对于preforkMPM，只有在需要将MaxClients设置成高于默认值256的时候才需要使用这个指令。要将此指令的值保持和MaxClients一样。
对于workerMPM，只有在需要将MaxClients和ThreadsPerChild设置成需要超过默认值16个子进程的时候才需要使用这个指令。不要将该指令的值设置的比MaxClients 和ThreadsPerChild需要的子进程数量高。
注意：
Apache在编译时内部有一个硬限制"ServerLimit 20000"(对于preforkMPM为"ServerLimit 200000")。不能超越这个限制。