一、多道处理模块MPM介绍
Apache HTTP 服务器被设计为一个功能强大,并且灵活的 web 服务器, 可以在很多平台与环境中工作。不同平台和不同的环境往往需要不同 的特性,或可能以不同的方式实现相同的特性最有效率。Apache 通过模块化的设计来适应各种环境。这种设计允许网站管理员通过在 编译时或运行时,选择哪些模块将会加载在服务器中,来选择服务器特性。 Apache 2.0 扩展此模块化设计到最基本的 web 服务器功能。 它提供了可以选择的多处理模块(MPM),用来绑定到网络端口上,接受请求, 以及调度子进程处理请求。
在用户看来,MPM 很像其它 Apache 模块。主要是区别是,在任何时间, 必须有一个,而且只有一个 MPM 加载到服务器中。
二、选择MPM
MPM 必须在编译前,配置时指定,然后编译到服务器程序中。 仅当编译器知道使用了线程时,它才有能力优化许多函数。
为了使用指定的 MPM,请在执行 configure
时,使用参数 --with-mpm=NAME
。NAME 是指定的 MPM 名称,我们只可以指定其中一个MPM模块。
编译完成后,可以使用 ./httpd -l
来确定选择的 MPM。 此命令会列出编译到服务器程序中的所有模块,包括 MPM。 Unix/Linux支持三种MPM, Prefork, worker, event,其中event模型在apache2.2版本是测试版,不建议在生产环境中使用,到apache2.4,event模型是稳定版。
可以使用 httpd -l
来确定选择的 MPM。 此命令会列出编译到服务器程序中的所有模块,包括 MPM。
[[email protected] ~]# httpd -l Compiled in modules: core.c # 核心 prefork.c # 编译的MPM模块 http_core.c mod_so.c # 支持DSO动态模块加载
prefork
prefork 为多路模块MPM 实现了一个进程模型,预派生的web服务器。prefork 适用于没有线程安全库,需要避免线程兼容性问题的系统。它是要求将每个请求相互独立的情况下最好的MPM,这样一个请求出现问题,不至于影响其他的请求。
prefork模式使用多个子进程,每个子进程在某个确定的时间只能维持一个连接。在大多数平台上,Prefork MPM在效率上要比Worker MPM 要高,但是内存使用大的多。prefork在Linux下工作,比worker更有优势。
一个单独的控制进程(父进程)负责生产子进程,这些子进程用于监听请求并作出应答。apache 总是试图保持一个备用的(spare)或是空闲的子进程用于迎接即将到来的请求。这样客户端就无需在得到服务前等候子进程的产生。在unix系统中,父进程通常是以root 身份运行以便绑定80端口,而apache生产的子进程通常一个低特权的用户运行。User和Group指令用于配置配置子进程的低特权用户。运行子进程的用户必须要对他所服务的内容用读取的权限,但是对服务内容之外的其他资源必须拥有尽可能少的权限
当httpd服务启动之后,会启动一个主进程(master process),它负责监听用户请求,以及派生和销毁子进程。它并不处理用户请求,一旦请求来了之后,调度其子进程(work process)来响应,然后继续监听其他请求。
需要考虑的是:刚启动的时候,创建多少空闲进程呢?为了快速响应用户请求,会创建几个空闲进程,当请求来了,可以快速的响应。如果请求太多,那么则会派生更多的进程来响应请求,但是假设到了晚上,访问量不大时,我们应该把多余的空闲进程回收,以免占用资源。
master process的主要作用:
1、启动服务时绑定特权端口
2、派发和回收子进程
3、读取分析主配置文件
4、监听用户请求并且调度子进程来响应
配置:编辑主配置文件 /etc/httpd/conf/httpd.conf
# prefork MPM <IfModule prefork.c> # 判断是否有prefork.c这个模块,有就生效,否则无效 StartServers 8 # 默认启动的工作进程数 MinSpareServers 5 # 保持的最少空闲进程数 MaxSpareServers 20 # 保持的最大空闲进程数 ServerLimit 256 # 保持的最大活动进程数 MaxClients 256 # 最大并发连接数 MaxRequestsPerChild 4000 # 每个子进程在生命周期能服务的最大请求数 </IfModule>
IfModule指令,意为判断模块是否存在,如果存在那么参数则生效,反之如果不存在此模块,参数将不会生效。
StartServer 5
指定服务器启动是建立的子进程的数量,prefork 默认为5。为了满足MinSpareServers设置的需要创建一个进程, 等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足 MinSpareServers设置的值为止。这就是预派生 (prefork)的由来。这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。
MinSpareServers 5
指定空闲子进程的最小数量,默认为5。假如当前空闲子进程数少于MinSpareServers,那么apache 将以每秒一个的速度产生新的子进程。此参数不要设置的太大
MaxSpareServers
设置空闲进程的最大数量,默认为10。如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程将杀死多余的子进程。此参数不要设置过大。如果该参数设置比MinSpareServers小,apache将会自动将其修改成"MinSpareServers+1”。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。
MaxClients 256
限定同一时间客户端最大接入的数量(单个进程并发线程数)。默认为256,任何超过MaxClients限制的请求都会进入等候队列,一旦一个链接被释放,队列中的请求将得到服务。如果要增大这个值,必须同时增加ServerLimit.理论上来说这个值越大,性能就越好。
ServerLimit 256
默认的MaxClient最大是256个线程,假如想设置更大的值,就需要加上ServerLimit这个数。 200000是ServerLimit这个参数的最大值。假如需要更大,则必须编译apache,此前都是无需重新编译apache。生效前提是,必须放在其他指令的前面。
MaxRequestsPerChild
每个子进程在其生存期内允许伺服的最大请求数量。默认为10000到达MaxRequestsPerChild的限制后,子进程将会结束。
如果MaxRequestsPerChild 为0,子进程将永远不会结束。将MaxRequestsPerChild 设置成非零值有两个好处:
- 可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。
- 给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。
对于KeepAlive链接,只有第一个请求会被计数。事实上,它改变了每个子进程限制最大链接数量的行为。
我们看看httpd进程:
[[email protected] ~]# ps -ef | grep httpd root 1812 1 0 10:00 ? 00:00:01 /usr/sbin/httpd # master process apache 1814 1812 0 10:00 ? 00:00:00 /usr/sbin/httpd # 以下都是 apache 1815 1812 0 10:00 ? 00:00:00 /usr/sbin/httpd # work process apache 1816 1812 0 10:00 ? 00:00:00 /usr/sbin/httpd apache 1817 1812 0 10:00 ? 00:00:00 /usr/sbin/httpd apache 1818 1812 0 10:00 ? 00:00:00 /usr/sbin/httpd apache 1819 1812 0 10:00 ? 00:00:00 /usr/sbin/httpd apache 1820 1812 0 10:00 ? 00:00:00 /usr/sbin/httpd apache 1821 1812 0 10:00 ? 00:00:00 /usr/sbin/httpd
Prefork是一个进程处理一个请求,在启动httpd的时候,如果选择的是这种模式,会首先创建一个主进程(控制进程)和StartServers个子进程,可以看到StartServers为8个.由于进程和进程之间是独享内存的,所以一个进程崩溃了不会影响到其他的进程,所以Prefork模式的稳定性比较好,但是进程多了消耗的内存会比较大.
主进程在创建了StartServers个子进程后,为了满足MinSpareServer的设置需求,会先创建一个进程,等待一秒,创建二个进程,再等待一秒,创建四个进程....以几何数增加创建的进程,最多达到每秒创建32个,直到满足MinSpareServer的设置(可以看到以下的MinSpareServer为5),这就是预派生(Prefork)的由来,这样不必等到有请求到来时才花时间创建新的进程,提高了系统响应速度以增加性能.
worker
worker MPM 使用多个子进程,每个子进程有多个线程。每个线程在每个确定的时间只能维持一个连接。通常来说,在一个高流量的HTTP服务器上,Worker MPM 是个比较好的选择,因为Worker MPM 的内存使用比Prefork MPM 要低的多。但是worker MPM 也有缺陷。如果一个线程崩溃,整个进程就会连同其任何线程一起“死掉”,由于线程共享内存空间,所以一个程序在运行时必须被系统识别为 “每个线程都是安全的”。
当第一个用户请求到达的时候线程发现需要复制文件,通过内核将文件复制给其进程,所以第二个用户请求同一个文件,对于第二个线程来说这个文件已存在,因为是公用同一个空间,所以速度得到提升;
其缺点:线程很有可能产生资源争用,并不是全状态并行。所以一个进程里不能启动太多线程,所以可启动多个进程从其启动的进程再启多个线程,但无论如何每个线程也都是一个独立的执行实体(执行必须给cpu资源)
更改apache的MPM为woker模式
我们是通过yum安装的httpd,它默认已经编译了prefork, worker两个MPM,所以我们可以切换。如果是手动编译的话, 我们仅能指定一个--with-mpm=NAME。
编辑配置文件/etc/sysconfig/httpd:
# vi /etc/sysconfig/httd # 把下面这一行的注释去掉 HTTPD=/usr/sbin/httpd.worker # 切换模式必须重启服务 # service httpd restart
worker默认的配置:
<IfModule worker.c> 如果有这个模块就启用 StartServers 4 # 启动的子进程数 MaxClients 300 # 并发请求最大数 MinSpareThreads 25 # 最小空闲线程数 total MaxSpareThreads 75 # 最大空闲线程数 total ThreadsPerChild 25 # 每个子进程可生成的线程数 MaxRequestsPerChild 0 # 每个子进程可服务的最大请求数,0表示不限制
[[email protected] ~]# ps -ef | grep httpd root 2395 1 0 15:36 ? 00:00:00 /usr/sbin/httpd.worker apache 2397 2395 0 15:36 ? 00:00:00 /usr/sbin/httpd.worker apache 2398 2395 0 15:36 ? 00:00:00 /usr/sbin/httpd.worker apache 2399 2395 0 15:36 ? 00:00:00 /usr/sbin/httpd.worker
worker的工作原理是,由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,每个线程处理一个请求,线程是共享内存空间的,所以一个线程崩溃会导致在这个进程下的所有线程都崩溃,所以他的稳定性没有Prefork好,但是内存使用率比Prefork低。同样,为了不在请求到来时再生成线程,MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而MaxClients设置了所有子进程中的线程总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。
MinSpareThreads和MaxSpareThreads的最大缺省值分别是25和75。这两个参数对Apache的性能影响并不大,可以按照实际情况相应调节。
ThreadsPerChild是worker 中影响性能最重要的一个指标,Worker模式下所能同时处理的请求总数是由StartServers总数乘以ThreadsPerChild的值决定的,应该大于等于MaxClients
参考:
http://blog.chinaunix.net/uid-20441206-id-3360689.html
http://blog.chinaunix.net/uid-17238776-id-4353851.html
http://www.cnblogs.com/ghj1976/archive/2011/01/11/1932764.html
Apache服务器中prefork和worker工作模式