介绍

Apache HTTP 服务器被设计为一个功能强大,并且灵活的 web 服务器,可以在很多平台与环境中工作。不同平台和不同的环境往往需要不同的特性,或可能以不同的方式实现相同的特性最有效率。Apache httpd通过模块化的设计来适应各种环境。这种设计允许网站管理员通过在编译时或运行时,选择哪些模块将会加载在服务器中,来选择服务器特性。

Apache HTTP 服务器 2.0 扩展此模块化设计到最基本的 web 服务器功能,它提供了可以选择的多处理模块(MPM),用来绑定到网络端口上,接受请求,以及调度子进程处理请求。

扩展到这一级别的服务器模块化设计,带来两个重要的好处:

  • Apache httpd 能更优雅,更高效率的支持不同的平台。尤其是Apache httpd 的 Windows 版本现在更有效率了,因为mpm_winnt 能使用原生网络特性取代在Apache httpd 1.3 中使用的 POSIX 层。它也可以扩展到其它平台来使用专用的 MPM。

  • Apache httpd 能更好的为有特殊要求的站点定制。例如,要求更高伸缩性的站点可以选择使用线程的 MPM,即worker 或 event;需要可靠性或者与旧软件兼容的站点可以使用prefork。


在用户看来,MPM 很像其它 Apache httpd 模块。主要是区别是,在任何时间,必须有一个,而且只有一个 MPM 加载到服务器中。


可用的MPM列表:

beos专门针对BeOS优化过的多路处理模块(MPM),此模块是BeOS系统的默认MPM模块
mpmt_os2专门针对OS/2优化过的混合多进程、多线程、多路处理模块(MPM),此模块是OS/2系统的默认MPM模块
 mpm_netware专门为Novell NetWare优化的、线程化的多路处理模块(MPM),此模块是NetWare系统的默认MPM模块
mpm_winnt用户Windows系统系列的MPM,此模块也是Windows系统的默认MPM模块
work线程型的MPM,实现了一个混合的多线程多处理MPM,允许一个子进程中包含多个线程,相对于Prefork,Worker是Apache2.0版本中新增加的支持多线程和多进程混合模型的MPM。由于使用多进程,再有每个进程派生出多线程来处理,所以可以处理相对海量的请求,而系统资源的开销要小于基于进程的服务器。这种类型的MPM工作方式将是Apache以后的发展趋势
preforkprefork是Unix/Linux平台上默认的MPM,它采用的预派生子进程方式也是Apache 1.3中采用的模式。prefork本身是不使用线程的,为了保持兼容性,所以Apache 2.0版本中还使用它,另一方面,prefork用单独的子进程来处理不同的请求,每个进程之间是独立的,这也使它成为最稳定的MPM之一
event
默认MPM

下表列出了不同系统的默认 MPM。如果你不在编译时选择,那么它就是你将要使用的 MPM。

Netwarempm_netware
OS/2mpmt_os2
Unix/Linuxprefork,worker或event,取决于平台特性
Windowsmpm_winnt
构建MPM为静态模块

在全部平台中,MPM 都可以构建为静态模块。在构建时选择一种MPM,链接到服务器中。如果要改MPM,必须重新构建。

为了使用指定的MPM,请在执行configure 脚本时,使用参数--with-mpm=NAMENAME 是指定的MPM名称。

编译完成后,可以使用./httpd -l来确定选择的MPM。此命令会列出编译到服务器程序中的所有模块,包括 MPM

构建MPM为动态模块

在 Unix 或类似平台中,MPM可以构建为动态模块,与其它动态模块一样在运行时加载。构建 MPM 为动态模块允许通过修改LoadModule指令内容来改变MPM,而不用重新构建服务器程序。

在执行configure 脚本时,使用--enable-mpms-shared 选项可以启用此特性。当给出的参数为 all时,所有此平台支持的MPM模块都会被安装。还可以在参数中给出模块列表。

默认MPM,可以自动选择或者在执行configure脚本时通过--with-mpm选项来指定,然后出现在生成的服务器配置文件中。编辑LoadModule指令内容可以选择不同的MPM。

prefork,worker,event三种模式的区别

Apache 2.X  支持插入式并行处理模块,称为多路处理模块(MPM)。在编译apache时必须选择也只能选择一个MPM,对类UNIX系统,有几个不同的MPM可供选择,它们会影响到apache的速度和可伸缩性。

  Prefork MPM : 这个多路处理模块(MPM)实现了一个非线程型的、预派生的web服务器,它的工作方式类似于Apache 1.3。它适合于没有线程安全库,需要避免线程兼容性问题的系统。它是要求将每个请求相互独立的情况下最好的MPM,这样若一个请求出现问题就不会影响到其他请求。

  这个MPM具有很强的自我调节能力,只需要很少的配置指令调整。最重要的是将MaxClients设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。


  Worker MPM : 此多路处理模块(MPM)使网络服务器支持混合的多线程多进程。由于使用线程来处理请求,所以可以处理海量请求,而系统资源的开销小于基于进程的MPM。但是,它也使用了多进程,每个进程又有多个线程,以获得基于进程的MPM的稳定性。

  每个进程可以拥有的线程数量是固定的。服务器会根据负载情况增加或减少进程数量。一个单独的控制进程(父进程)负责子进程的建立。每个子进程可以建立ThreadsPerChild数量的服务线程和一个监听线程,该监听线程监听接入请求并将其传递给服务线程处理和应答。

  不管是Worker模式或是Prefork 模式,Apache总是试图保持一些备用的(spare)或者是空闲的子进程(空闲的服务线程池)用于迎接即将到来的请求。这样客户端就不需要在得到服务前等候子进程的产生。


  Event MPM:以上两种稳定的MPM方式在非常繁忙的服务器应用下都有些不足。尽管HTTP的Keepalive方式能减少TCP连接数量和网络负载,但是 Keepalive需要和服务进程或者线程绑定,这就导致一个繁忙的服务器会耗光所有的线程。 Event MPM是解决这个问题的一种新模型,它把服务进程从连接中分离出来。在服务器处理速度很快,同时具有非常高的点击率时,可用的线程数量就是关键的资源限 制,此时Event MPM方式是最有效的。一个以Worker MPM方式工作的繁忙服务器能够承受每秒好几万次的访问量(例如在大型新闻服务站点的高峰时),而Event MPM可以用来处理更高负载。值得注意的是,Event MPM不能在安全HTTP(HTTPS)访问下工作。


查看并配置Apache使用的MPM
  [root@GMQ ~]# httpd -l #→列出支持使用的非DSO模块
  Compiled in modules:
   core.c
   prefork.c
   http_core.c
   mod_so.c
  [root@GMQ ~]# httpd -M #→列出已经装载的所有模块(包含静态编译和动态加载的模块)
  Loaded Modules:
   core_module (static)
   mpm_prefork_module (static)
   http_module (static)
   so_module (static)
   auth_basic_module (shared)
   auth_digest_module (shared)
   authn_file_module (shared)
   authn_alias_module (shared)
   authn_anon_module (shared)
   authn_dbm_module (shared)
[root@GMQ ~]# vim /etc/sysconfig/httpd
#HTTPD=/usr/sbin/httpd.worker 
HTTPD=/usr/sbin/httpd.worker  #设置Apache使用的MPM 

MPM参数分析与设置
1)Apache Prefork模式:
[root@GMQ ~]# cat /etc/httpd/conf/httpd.conf #→查看prefork在apache里的默认配置
<IfModule prefork.c>
StartServers       8        #→默认启动的工作进程数;
MinSpareServers    5        #→最少空闲工作进程数,保存备用
MaxSpareServers   20        #→最大空闲工作进程数,保存备
ServerLimit      256        #→最大活动工作进程数;
MaxClients       256        #→并发请求的最大数;
MaxRequestsPerChild  4000   #→每个子进程在生命周期内所能够服务的最多请求个数
</IfModule>


   apache的prefork MPM 是应用最广的一个, 目前为止我使用的服务器都采用prefork, 因为它够稳定,而且我写的LNMP/LNMPA一键安装包也采用prefork为apache的默认MPM模式。

   prefork采用的是预派生子进程方式,用子进程处理不同的请求, 每个请求对应一个子进程,进程之间是彼此独立的。当apache启动后会先启动StartServers个子进程,等待1秒后会再创建两个,再等待1秒后创建4个,再一秒后创建8个这样直到创建满MinSpareServers个子进程为止,那么此时MinSpareServers个子进程会待命,这种待命模式不必在新请求到来时重新创建, 一定程度上加快了进程的响应速度。

   MaxSpareServers的值代表最大的待命进程数,如果待命进程数大于这个apache会自动kill掉多余没有启用的进程。如果站点负载交大, 内存足够多, 那么可以考虑加大MinSpareServers 和MaxSpareServers。有人问我那么apache一个子进程到底占用多大内存呢?其实这个跟apache加载的php模块有关, 还跟php处理的脚本有关,一般来说一个子进程大概占用2-10M左右。

   MaxRequestWorkers (在之前的版本中称之为MaxClients),此参数很重要, 其表示apache可以同时处理请求数,默认值是250, 我们一般都会将其加大很多, 但是不能大于250岂不是很坑爹? 别担心, apache同时提供了另一个指令ServerLimit,将这个指令和MaxRequestWorkers 设置相同即可,该指令用于修改apache默认256的限制,ServerLimit 的最大硬限制为200000, 也就是说理论上我们可以让apache同时处理20万的请求, 至于这20万请求过来之后apache是如何分配的就要看你的其他参数的设置了。

   MaxRequestsPerChild上面说到都是进程, 那么这个MaxRequestsPerChild就代表的是每一个进程所能够承受的最大请求数量, 如果某一个进程超过了这个数量则进程自动释放所有内存然后自杀掉。此值可以设置为0, 0就是说永远不结束, 这样做的弊端是进程占用内存过大而且容易内存溢出。不过对于KeepAlive链接, 只有第一个请求会被算进去, KeepAlive有效期类的其他请求将不作数。


2)Apache Worker模式:

[root@GMQ ~]# cat /etc/httpd/conf/httpd.conf#→查看worker在apache里的默认配置
<IfModule worker.c>
StartServers         4  #→启动的子进程的个数;
MaxClients         300  #→并发请求的最大数,保存备用;
MinSpareThreads     25  #→最小空闲线程数;保存备用;
MaxSpareThreads     75  #→最大空闲线程数;
ThreadsPerChild     25  #→每个子进程可生成的线程数;
MaxRequestsPerChild  0  #→每个子进程在生命周期内所能够服务的最多请求个数,0表示不限定;
</IfModule>


  worker的工作原理是,由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,各个线程独立地处理请求。同样,为了不在请求到来时再生成线程,MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而"MaxClients"设置了所有子进程中的线程总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。 

  "MinSpareThreads"和"MaxSpareThreads"的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大,可以按照实际情况相应调节。

  "ThreadsPerChild"是workerMPM中与性能相关最密切的指令。这个指令设置了每个进程建立的进程数。子进程在启动时建立这些线程后就不在建立新的线程了。每个进程所拥有的所有线程的总数足够大,以便可以处理可能的请求高峰。

  worker模式下所能同时处理的请求总数是由子进程总数乘以"ThreadsPerChild"值决定的,应该大于"MaxClients"。如果显式声明了"ServerLimit",那么它乘以ThreadsPerChild的值必须大于等于"MaxClients",而且"MaxClients"必须是"ThreadsPerChild"的整数倍,否则Apache将会自动调节到一个相应值(可能是个非期望值).


3)Apache Event模式: