概述: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则不须要频繁的建立销毁。