Apache下三种MPM模式:prefork,worker和event


MPM(Multi-Processing Module,多进程处理模块):
prefork,worker和event

查看Apache的模式,可以使用httpd -V命令来查看:

 /usr/local/apache2/bin/httpd  -V
Server version: Apache/2.2.29 (Unix)
Server built:   Aug 20 2015 20:11:21
Server's Module Magic Number: 20051115:36
Server loaded:  APR 1.5.1, APR-Util 1.5.3
Compiled using: APR 1.5.1, APR-Util 1.5.3
Architecture:   64-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)

 

编译的时候,通过configure的参数来指定
--with-mpm=prefork|worker|event

 cat /usr/local/apache2/build/config.nice"./configure" \
..."--with-apr=/usr/local/apr" \"--with-apr-util=/usr/local/apr-util" \"--with-z=/usr/local" \"--with-mpm=prefork" \
....

 

可以编译为三种都支持,通过修改配置来更换
--enable-mpms-shared=all

modules目录下,会自动编译出三个MPM的so文件,
在httpd.conf中,修改加载的模块来改变MPM的模式:
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

prefork 

"It's probably not advisable to use prefork unless you need a module that's not thread safe."
prefork模式,很古老,非常稳定的模式,不建议使用的模式,除非是在使用一个非线程安全的模块。

为了减少频繁创建和销毁进程的开销,Apache在启动之初,预先fork一些子进程,然后等待请求进来。

每个子进程只有一个线程,在一个时间点内,只能处理一个请求。

优点:成熟稳定,兼容所有新老模块。
MOD_PHP拓展不需要支持线程安全,不需要担心线程安全的问题。

缺点:一个进程相对占用更多的系统资源,消耗更多的内存。
不擅长处理高并发请求,高并发场景下会将请求放进队列中,
一直等到有可用进程,请求才会被处理。

使用场景:
尽量不推荐在此模式下裕兴,除非模块无法在线程模式下运行。
PHP在非线程安全模下,推荐使用FastCGI和php-fpm模式。


worker 

线程模式,内存占用会少一些,在高并发方面表现的会更好。

启动时会fork几个子进程,每个子进程创建一些线程,同时包括一个监听线程。

每个请求过来,会被分配到1个线程来服务。
线程比起进程会更轻量,线程通常会共享父进程的内存空间。
在高并发的场景下,比prefork有更多的可用线程,性能表现会更优秀一些。

如果一个线程异常挂了,会导致父进程连同其他正常的子线程都挂了。
为了防止这场异常场景出现,就需要使用多个进程再加多线程,如果某个线程出现异常,受影响的只是Apache的一部分服务,而不是整个服务。

优点:占据更少的内存,高并发下表现更优秀。

缺点:必须考虑线程安全的问题,因为多个子线程是共享父进程的内存地址的。
keep-alive的长连接方式,是为了让下一次的socket通信复用之前创建的连接,从而,减少连接的创建和销毁的系统开销。保持连接,会让某个进程或者线程一直处于等待状态,即使没有数据过来。如果使用keep-alive的长连接方式,某个线程会一直被占据,需要一直等待到超时才会被释放。

使用场景:
使用Apache httpd 2.2或2.4版本,同时打算运行SSL服务。
除非兼容性问题解决不了,一般比较推荐worker模式。

event


"it's just been moved from 'experimental' to 'stable' status in Apache 2.4."
event MPM,需要Linux系统(Linux 2.6+)对EPoll的支持,同时建议在httpd 2.4.x版本下使用。
event 和worker模式很像,解决了keep-alive场景下,长期被占用的线程的资源浪费问题。
event MPM中,会有一个专门的线程来管理keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放,增强了高并发场景下的请求处理能力。
event MPM在遇到某些不兼容的模块时会失效,将会回退到worker模式,一个工作线程处理一个请求。


使用场景:
使用apache httpd 2.4,同时使用到多线程,event是最佳的运行模式。

httpd 2.2.x文档下:

Warning
This MPM is experimental, so it may or may not work as expected.

This MPM does not perform well on older platforms which lack good threading, but the requirement for EPoll or KQueue makes this moot.

To use this MPM on FreeBSD, FreeBSD 5.3 or higher is recommended. However, it is possible to run this MPM on FreeBSD 5.2.1, if you use libkse (see man libmap.conf).
For NetBSD, at least version 2.0 is recommended.
For Linux, a 2.6 kernel is recommended. It is also necessary to ensure that your version of glibc has been compiled with support for EPoll.