httpd 服务器的三大引擎 prefork、worker、event分析

概述:html

     httpd 2.2以前(2.2也包含在内),不支持动态切换MPM。且在编译时候,只能指定使用哪一种MPM。若是,提供了 prefork、worker、event ,要改变MPM,只能在启动httpd服务器程序的时候,指定使用:linux

  /usr/sbin/httpd
  /usr/sbin/httpd.event
  /usr/sbin/httpd.worker

中的那一个二进制程序。web

     httpd 2.4就支持动态切换MPM,在配置文件中使用【LoadModule】指令就能够实现MPM的切换了。条件:咱们编译httpd时,要把:prefork、worker、event都编译成模块。apache

1、httpd服务器工做在 prefork 模型是一个进程服务响应一个用户请求windows

 启动httpd服务缓存

[root@stu13 httpd-2.4]# ./bin/apachectl start
[root@stu13 httpd-2.4]# pstree | grep httpd
     |-httpd---5*[httpd]

查看httpd服务器工做的MPM是什么?安全

[root@stu13 httpd-2.4]# ./bin/httpd -M | grep mpm
 mpm_prefork_module (shared)

说明:bash

    从【pstree】命令的显示结果,能够看到启动httpd服务器时就启动5个httpd服务进程用来准备接收web请求。服务器

    固然这5个进程都是由会话领导进程(该进程的全部者是root管理员)fork()而来。主进程管理子进程,如:回收子进程、建立子进程等。而响应用户访问请求的则是子进程。网络

    当用户向httpd服务器,发起访问资源链接请求的时候,

httpd服务器会根据<IfModule mpm_prefork_module>指令定义的参数维护进程池中的进程。

当用户向httpd服务器发起链接请求的时候,httpd的主进程就会从进程池中派一个子进程来负责响应用户的请求,若是该服务器的并发请求量为100的话,一会儿就使用完,进程池中空闲进程数(咱们定义了进程池中最小空闲进程数为5),90个用户的链接请求只好等待。这时主进程fork()出子进程,而后才能响应处于等待90个用户的链接请求。虽然是一个进程负责响应一个用户的请求,当该进程完成了用户的请求以后,会话领导进程并不会立刻kill掉该进程。而是使用了重用的机制。意思是在进程的生命周期内它响应完负责的用户请求后,还能够响应后续的用户请求。这是为了减小消耗在建立进程上面的时间。实现快速地响应用户请求的一种机制。假如过了一会,咱们的httpd服务器已经处理完这100个并发用户的请求了。根据后续用户的并发用户数目有三种状况:

(1)、后续的并发用户数小于10的话:

     领导会话进程,为了响应这100个并发请求的用户,而fork()出的子进程,除了用来响应后面的

     用户链接请求的进程以外,其它空闲进程通通被kill掉。只保留必定数目的空闲进程。如最小空      闲进程数为:5( MinSpareServers          5)、最大空闲进程数为:10(MaxSpareServers         10)

(2)、后续的并发用户数大于10而小于150的话:

     响应100个并发用户链接请求的进程都获得了重用,但因为在处理过程当中进程要不断申请和释放      内存,次数(处理用户的请求次数)多了就会形成一些内存垃圾,就会影响系统的稳定性且影响了

     系统的有效利用,因此会话进程的生命周期是有限的,会话管理进程要kill掉一些进程。而在进

     程的生命周期内,可以处理的用户请求数量是能够

     设置的。httpd 2.2 版本和httpd 2.4版本的设置以下:

     httpd 2.2     MaxRequestsPerChild    4000
     httpd 2.4     MaxConnectionsPerChild   0

 因此,领导进程fork()子进程是不免的。意思是说:消耗在建立进程和销毁进程中的时间是不免的。

     若是,咱们的服务器性能很好的话,能够增长进程能够处理的用户请求的数量,可是可能会影响

     系统的稳定,产生一些内存垃圾。可是减小了fork()进程和kill进程的时间。在必定的程序上,

     提升了响应用户链接请求的速度。

     若是,不调整进程的生命周期内能够处理多少个用户的链接请求数的话,就要花费大量的时间

     (若是咱们的服务器比较繁忙的话)fork()进程,kill进程.会在必定程度上影响响应用户请求的

     速度的。

(3)、后续的并发用户请求数大于150的话;

     有可能会出现,有可能会出现链接请求超时的状况。若是咱们的接收链接的缓存不够大的话,

     有些用户的请求链接都没法接收下来。无论服务器是否可以处理,都应该把请求接收下来再说。咱们能够调大该缓存:

     [root@stu13 ~]# cat /proc/sys/net/ipv4/tcp_mem
     46368   61824   92736
     [root@stu13 ~]# cat /proc/sys/net/ipv4/tcp_rmem
     4096    87380   1978368
     [root@stu13 ~]# cat /proc/sys/net/ipv4/tcp_wmem
     4096    16384   1978368

 固然,若是服务器的性能很好的话,咱们能够调大处理的并发用户数量,httpd 2.2 与 httpd 2.4中定义以下:

    httpd 2.2     MaxClients             300  
    httpd 2.4     MaxRequestWorkers      150

    可是,若是调大了并发用户数(服务器的性能条件下),虽然一次性能够处理的用户请求数增长了,可是在服务器上进程的切换的次数也增长了。由于进程的切换是浪费CPU时间周期的。因此,咱们要为服务器定作一个黄金比例。既能处理更多的用户并发请求,浪费在进程间切换的时间又很合理。

prefork模型的配置以下:

<IfModule mpm_prefork_module>
    StartServers             5      服务器启动时就fork()出5个进程,等待用户链接请求
    MinSpareServers          5      服务器在等待客户端链接请求的最小空闲进程数。
    MaxSpareServers         10      服务器在等待客户端链接请求的最大空闲进程数。
    MaxRequestWorkers      150      容许最大的用户并发请求数。
    MaxConnectionsPerChild   0      在进程的生命周期内,它能够服务多少个请求。
</IfModule>

httpd服务器刚启动没有接收客户端链接请求时候,所占据常驻物理内存大小为

[root@stu13 ~]./test/test.sh
Date: 2014/08/10_16:30:05
user     pid     vsz      rss      comm
root     19506   5252     2196     httpd
daemon   19507   5252     1684     httpd
daemon   19508   5252     1684     httpd
daemon   19509   5252     1684     httpd
daemon   19510   5252     1684     httpd
daemon   19511   5252     1684     httpd
--------------------total_Rss---------------------
10616

说明:

    httpd服务器全部进程占据的常驻物理内存集约为:10M.


二、对该httpd进行压力测试,并发用户数为:100,共发起3000个请求。暂停2秒。共测试40次。

[root@stu13 httpd-2.4]# declare -i num=40
[root@stu13 httpd-2.4]# while [ "$num" -gt 0 ]; do ab -c 100 -n 3000 http://192.168.60.99/index.html; sleep 2 ; let num--; done
.....
Date: 2014/08/10_16:33:02
user     pid     vsz      rss      comm
root     19506   5252     2216     httpd
daemon   19509   5384     2264     httpd
daemon   20311   5384     2244     httpd
daemon   20459   5384     2244     httpd
daemon   20519   5384     2244     httpd
daemon   20555   5384     2244     httpd
daemon   20615   5384     2244     httpd
daemon   20856   5384     2244     httpd
daemon   20944   5384     2244     httpd
daemon   21036   5384     2244     httpd
daemon   21089   5384     2244     httpd
--------------------total_Rss---------------------
24676

Date: 2014/08/10_16:33:03
user     pid     vsz      rss      comm
root     19506   5252     2216     httpd
daemon   19509   5384     2264     httpd
daemon   20311   5384     2244     httpd
daemon   20459   5384     2244     httpd
daemon   20519   5384     2244     httpd
daemon   20555   5384     2244     httpd
daemon   20615   5384     2244     httpd
daemon   20856   5384     2244     httpd
daemon   20944   5384     2244     httpd
daemon   21036   5384     2244     httpd
daemon   21089   5384     2244     httpd
--------------------total_Rss---------------------
24676

说明:

   进行压力测试后,httpd服务器常驻内存集大小为:24675,约为:24M.

prefork模式,使用一个进程服务一个用户请求。因为进程打开的资源是独享,若是,用户访问的资源相同也要打开屡次的。可是,比较稳定的。

   因为prefork模型的,服务用户请求的会话进程要不断建立、销毁。也就是进程号PID不断发生变化,因此很难作到把会话进程绑定在CPU上(使用进程号作绑定)。若是咱们的服务器,有多颗CUP的话,可使用指定的CPU处理中断请求。

    prefork 工做模式,负责监听/响应的是主进程(属主为root的httpd会话领导进程)是基于 select/poll 实现网络IO利复的。这样服务器就能够实现并发了。但因为 select/poll自己的局限性,理论上并发能力上限为:1024。

2、worker 工做模型是

    一个线程服务一个用户的链接请求。线程比进程更轻量级,建立和消耗的速度比进程的建立和消耗要快得多。线程之间还能够共享资源,如:打开的文件描述符等。这样若是:两个客户端请求的是同一个文件,就不须要从磁盘上加载两次了,速度要比基于进程的响应速度快。但线程的管理要比进程复杂得多。线程之间不少资源是共享的,因此它没有prefork模型,一个进程服务一个服务请求那么安全稳定。何况,linux不是真线程的操做系统,worker 与 prefork 这两种模型,在linux上的表现几乎都同样。一般使用prefork模型。windows 是真线程的操做系统,它对线程的支持就很好。

 启动httpd服务器

[root@stu13 httpd-2.4]# ./bin/apachectl start
[root@stu13 httpd-2.4]# pstree | grep httpd
     |-httpd---2*[httpd---26*[{httpd}]]

查看当前httpd服务器使用的MPM是什么?

[root@stu13 httpd-2.4]# ./bin/httpd -M | grep mpm
 mpm_worker_module (shared)

说明:

    从【pstree】的显示结果能够看出,httpd服务器刚起动就建立了2个子进程,且这2个子进程又建立了25个线程用来等待服务客户端的链接请求的。刚启动httpd服务器时(没有接收客户端链接请求),

worker 的模型以下:分析评估应用,能够调节下述的参数来调节httpd服务器的并发能力的。

<IfModule mpm_worker_module>
    StartServers             2         服务器刚启动的时候就启动两个进程,这两个进程共生
                                        成25个线程用来等待客户端的链接请求的。
    MinSpareThreads         25         最少保持25个线程处于空闲状态
    MaxSpareThreads         75         最多保持75个纯程处于空闲状态
    ThreadsPerChild         25         每一个进程最多容许生成25个线程
    MaxRequestWorkers      150         并发数为150
    MaxConnectionsPerChild   0         在线程的生命周期内,
                                        线程容许服务的客户端链接的个数。
</IfModule>

一、httpd服务器刚启动没有接收客户端链接请求时候,所占据常驻物理内存大小为

[root@stu13 ~]./test/test.sh
Date: 2014/08/10_16:40:34
user     pid     vsz      rss      comm
root     23955   5428     2372     httpd
daemon   23956   283160   2092     httpd
daemon   23957   283160   2096     httpd
--------------------total_Rss---------------------
6560

二、对该httpd进行压力测试,

[root@stu13 httpd-2.4]# declare -i num=40
[root@stu13 httpd-2.4]# while [ "$num" -gt 0 ]; do ab -c 100 -n 3000 http://192.168.60.99/index.html; sleep 2 ; let num--; done
.....
Date: 2014/08/10_16:59:37
user     pid     vsz      rss      comm
root     28920   5428     2384     httpd
daemon   28921   285476   3740     httpd
daemon   28922   285476   3752     httpd
daemon   29110   285476   3720     httpd
daemon   30774   285476   3712     httpd
--------------------total_Rss---------------------
17308

Date: 2014/08/10_16:59:38
user     pid     vsz      rss      comm
root     28920   5428     2384     httpd
daemon   28921   285476   3740     httpd
daemon   28922   285476   3752     httpd
daemon   29110   285476   3720     httpd
--------------------total_Rss---------------------
13596

说明:

    由于,线程池中定义了,每一个进程最多能够生成25个线程, 假如:此时,httpd服务器共有4个进程,每一个进程都产生了25个线程,4个进程都满负荷运转了,

    可是,仍是有不少用户在等待,这时候主进程(会话领导进程),又会fork()出进程,子进程又生成线程来服务客户端的链接请求的。进程的线程在不断服务链接请求,会不断申请内存释放内存,次数多了,不免会产生内存垃圾的。影响系统的稳定。因此,httpd服务器要不断使用新的进程替换老的进程。、


3、event:

   是基于信号驱动I/O 通知机制。工做方式是:使用每线程服务N个用户请求。event的工做模型要优于prefork和worker.

启动httpd服务

[root@stu13 httpd-2.4]# ./bin/apachectl start
[root@stu13 httpd-2.4]# pstree | grep httpd
     |-httpd---2*[httpd---26*[{httpd}]]

一、查看 httpd服务器的工用模型

[root@stu13 httpd-2.4]# ./bin/httpd  -M | grep mpm
 mpm_event_module (shared)

httpd服务器工做在event模式下线程池的控制。也worker的线程池很类似,但event的工做方式是:一个线程服务N个用户请求。

<IfModule mpm_event_module>
    StartServers             2         服务器启动的时候就生成2个子进程,
                                       该子进程共生成25个线程等待客户端的链接请求
    MinSpareThreads         25         线程池中保持最少25个空闲线程。
    MaxSpareThreads         75         线程池中保持最多75个空闲线程。
    ThreadsPerChild         25         每一个进程最多能够生成25个线程。
    MaxRequestWorkers      150         最大并发用户数为:150
    MaxConnectionsPerChild   0          线程可以服务的用户请求数据。 0 表示不作限定。
</IfModule>

httpd服务器没有服务用户请求时,所占据常驻物理集大小为

[root@stu13 ~]# test/test.sh
Date: 2014/08/10_17:04:58
user     pid     vsz      rss      comm
root     30948   5436     2352     httpd
daemon   30949   283168   2084     httpd
daemon   30950   283168   2088     httpd
--------------------total_Rss---------------------
6524

二、对该httpd进行压力测试,

[root@stu13 httpd-2.4]# declare -i num=40
[root@stu13 httpd-2.4]# while [ "$num" -gt 0 ]; do ab -c 100 -n 3000 http://192.168.60.99/index.html; sleep 2 ; let num--; done
.....
Date: 2014/08/10_17:08:26
user     pid     vsz      rss      comm
root     30948   5436     2352     httpd
daemon   30949   287172   6076     httpd
daemon   30950   288372   6704     httpd
--------------------total_Rss---------------------
15132

Date: 2014/08/10_17:08:27
user     pid     vsz      rss      comm
root     30948   5436     2352     httpd
daemon   30949   287172   6076     httpd
daemon   30950   288372   6704     httpd
--------------------total_Rss---------------------
15132

说明:

    经过并发测试后,进程的进程号并无改变。则工做在 worker模型下的,压力测试后,进程号已经发生了改变。

    event 和 worker的线程池的配置都同样,因为 event 是基于信号驱动I/O 通知机制,每一个进程能够服务N个用户请求。

    而worker是一个线程服务一个请求。在请求没有完成以前,该线程是与它服务的请求绑定的。

worker须要大量的建立进程生成线程,销毁线程,杀死进程的过程。而event则不须要频繁的建立销毁。

相关文章
相关标签/搜索