Apache运行模式MPM详解
一、理论概述
Web服务器Apache目前一共有三种稳定的MPM(Multi-Processing Module,多线程处理模块)模式。
Prefork :进程模式
Worker :线程模式
Event : 事件模式 (2.4版本开始稳定使用)
Prefork运行模式详解:
1、Prefork MPM :Prefork MPM实现了一个非线程的、预派生的Web服务器。它在Apache启动之初,就先预派生一些子进程,然后等待连接;可以减少频繁创建和销毁进程的开销,每个子进程只有一个线程,在一个时间点内,只能处理一个请求,这是一个成熟稳定,可以兼容新老模块,也不需要担心线程安全问题,但是一个进程相对占用资源,消耗大量内存,不擅长处理高并发的场景。
最重要的是将MaxRequestWorkers设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。
注:Prefork 是基于多进程的模式
优点:因为每个进程使用独立的内存空间,所以比较安全,一个进程坏了,不会影响其他进程。
缺点:占用的内存比较大。
如果在预编译的时候没有指定MPM的模式,默认使用的是Prefork模式。
[root@localhost ~]# vim /etc/httpd/httpd.conf
如图上所示:在Apache的配置文件中,可以看出使用的是MPM的哪个模式,我的Apache在预编译的时候,使用参数让Apache三种模式都支持,但指定了使用Event模式,所以这里Event行前的#是被取消掉的!!!
2、Worker MPM:和Prefork模式相比,worker使用了多进程和多线程的混合模式,worker模式也同样会先预派生一些子进程,然后每个子进程创建一些线程,同时包括一些监听线程,每个请求过来会被分配到一个线程来服务。线程比起进程来更轻量,因为线程是通过共享父进程的内存空间,因此,内存的占用会减少一些,在高并发的场景下会比Prefork有更多可用的线程,表现会更优秀一些,另外,如果一个线程出了问题也会导致同一个进程下的线程出现问题,如果是多个线程出现问题,也只是影响Apache的一部分,而不是全部,由于用到多进程多线程,需要考虑到线程的安全了,在使用Keep-alive长连接的时候,某个线程会一直被占用,即使中间没有请求需要等待到超时才会被释放(该问题在Prefork模式下也存在)。
注:Worker MPM
优点:可以处理海量请求,而系统资源的开销小。原因:一个进程中包括多个线程,多个线程之间可以共享内存,所以占用的内存资源比较少。
缺点:不太安全,如果一个线程坏了,整个进程都要坏了,另外存在Keep-alive长连接占用资源时间过长。
如何避免进程中某个线程坏了?一个进程中所有线程完成一定数量的请求后,自动关闭,再重新打开,就可以避免内存溢出等问题。
不管是Worker模式还是Prefork模式,Apache总是试图保持一些备用的(Spare)或者是空闲的子进程(空闲的服务线程池),用于接受客户端即将到来的请求,这样客户端就不需要再等到服务前等候子进程的产生。
3、 Event MPM :event模式是在2.4版本中才稳定发布的模式,这就是Apache最新的工作模式,他和worker模式很像,不同的是在于它解决了Keep-alive长连接的时候占用线程资源被浪费的问题,在event工作模式中,会有一些专门的线程用来管理这些Keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放,这增强了在高并发场景下的请求处理。
当某个连接没有请求时,会主动关闭连接,在Worker模式下,必须要等Keep-alive超时,才可以释放。
在./configure配置编译参数的时候,可以使用 --with-mpm=prefork | worker | event 来指定编译为哪一种MPM,当然也可以用编译为三种都成 --enable-mpms-shared=all,这样在编译的时候会在modules目录下自动编译出三个MPM文件的so,然后通过修改httpd.conf配置文件更改MPM。
4、查看当前使用的是那种MPM
[root@localhost ~]# /usr/local/apache/bin/apachectl -M | grep event #可以查看到使用的是什么模式
mpm_event_module (shared)
也可以使用:/usr/local/apache/bin/apachectl -V 查看MPM ; 如下;
使用:/usr/local/apache/bin/httpd -M | grep event 和 /usr/local/apache/bin/httpd -V 和上述是一样的效果;
总结:
RHEL6/7系统自带的apache默认采用的是Prefork进程模式,在编译apache源码时,如果不用--with-mpm显式指定某种MPM,Prefork就是缺省的MPM;
HTTP 2.4 新特性:
1)MPM支持在运行时装载
指定启用:
--enable-mpms-shared=all --with-mpm=event ##把所有支持的MPM都编译出来,但启用默认的是event
2)支持event 2.2版本也支持,只不过是测试版本
3)异步读写
4)在每模块及每目录上指定日志级别
5)每请求配置;<If> <Elseif>
6)增强版的表达式分析器
7)毫秒级的keepalive timeout,使用ms指定为毫秒
8) 支持主机名的虚拟主机不在需要NameVirtualHost指令
9)支持使用自定义变量
新增一些模块:mod_proxy_fcgi(基于fcgi方式调用执行环境)
mod_ratelimit (用于做速率限定)
mod_request (对请求方法做限定)
mod_remoteip (对远端IP做限定)
对于基于IP的访问做了修改,不在使用order,allow,deny这些机制;而是统一使用require进行调整MPM模块则直接修改主配置文件中的LoadModule指定即可。
二、优化部分
1、对Prefork模块进行设置,修改apache的httpd-mpm.conf配置
[root@lamp ~]# cd /etc/httpd/extra/
[root@lamp extra]# mv /etc/httpd/extra/httpd-mpm.conf ./httpd-mpm.conf.bak
[root@lamp extra]# egrep -v "#|^$" ./httpd-mpm.conf.bak > ./httpd-mpm.conf
[root@lamp extra]#
先将http-mpm.conf 中的注释行和空行过滤掉
注释:
StartServers 5 在初始化的时候打开5个进程
MinSpareServers 5 最少有5个备用空闲进程
MaxSpareServers 10 最多10个备用空闲进程
MaxRequestWorkers 250 Apache最大的处理并发请求是250个
MaxConnectionsPerChild 0 这个一般不用,
添加:
ServerLimit 250 该参数是最大的进程数,由于Prefork模式进程和线程是一对一的,所以最大请求并发得和最大进程数相等。
针对于Prefork中参数数值的调整,还是需要根据实际情况(服务器性能,业务需求)来进行调整:
如果做5000个并发的Web,需要多少内存? 5000*2M/0.8/1024=12.2G,服务器大概需要14G——16G内存,
ServerLimit的大小,取决于你系统的资源,每个Apache进程默认大约占用2M内存,基本可以按照这个工时来计算,最大内存*80%/2M=ServerLimit (一个进程正常是1.6-1.7M,上述使用2M作为计算的)。
根据上面的描述,修改参数如下:
注释:MaxRequestsPerChild 1000 #每个子进程可以支持的请求数,累计到1000。会重启进程。存在长连接的话,一个长连接只能算一个。这可以设置为0,因为一个进程关闭,所有的线程也都关了。
额外参数:
MaxKeepAliveRequests 200 # 限制KeepAlive长链接最大处理200个请求。
目前用的MPM是Event,修改Apache配置文件,调整位Prefork:
修改为:
重新启动Apache之后发现,Apache预派生进程数变成5个:
注释:
5个预派生进程是Prefork默认的,Apache没有去读取我们修改过的http.mpm.conf文件。
在配置文件中,将该行的注释取消掉。
重启Apache查看预派生的进程数如下:
查看到httpd进程数52个,多的两个。一个是我们grep抓取时候的进程,还有一个是httpd的主进程。
一般对于数值的设定,够用就行。
如上:进程中第六列是每个进程占用我们资源大小,1536K。
[root@lamp extra]# ps -aux | grep httpd | awk '{sum += $6; n++};END{print sum/n}'
1546.46
[root@lamp extra]#
使用awk进行第六列自加。算出总量1546.46K。1M=1024K
比如:内存2G 20%的内存留给系统使用,最大可以处理多少Apache并发;
内存2G - 400M =1600M/1.5M = 1100并发数; 然后根据实际计算,修改Prefork_module参数;
watch 命令用于动态的观察Apache的最大连接数:
watch -n 1 "pgrep httpd | wc -l"
使用ab来进行测压:
[root@lamp ~]# yum install -y httpd-devel #ab是httpd-devel提供的,ab是最简单的测压工具
通过ab命令测试以及配合watch可以动态查看到进程数量的变化;等请求完成之后,进程数量不断减少至52;
2、对worker模块进行设置,修改apache的httpd-mpm.conf配置
worker比prefork内存资源使用少很多,适用于高并发,缺点就是一个线程崩掉了,整个进程就崩掉了,稳定性不如prefork。
修改Apache配置文件,将Prefork注释掉,启用worder;
重新启动Apache;
查看目前使用的MPM模块:如下
查看预派生进程数是不是变成worker默认的三个:如下
修改httpd.mpm.conf配置文件:如下(生产环境最常用的)
注释:
ServerLimit 64 最大的进程数限制
StartServers 5 最初建立的子进程
MinSpareThreads 25 最小空闲线程数
MaxSpareThreads 500 最大空闲线程数
ThreadsPerChild 150 每个进程包括150个线程数
ThreadLimit 200 一个进程下最大的线程数限制
MaxRequestWorkers 9600 表示Apache最多同时处理9600的并发请求,超过的进入队列等待;9600是64*150得到的;
此服务器配置:最多进程数:64个,最多线程数(最大并发数)64*150=9600,不可以超过64*200=12800
然后保存配置 ,重启Apache,即可生效;
案例:
如果MaxRequestsPerChild 30000 这样配置会有什么结果?
结果:一但到30000次请求 , 那150个线程都关了,会出大量闪断情况。
3、Event模式,了解以下即可;
总结:
Apache httpd 能更好的为有特殊要求的站点定制。例如,要求 更高伸缩性的站点可以选择使用线程的 MPM,即 worker 或 event; 需要可靠性或者与旧软件兼容的站点可以使用 prefork
源文地址:https://blog.csdn.net/weixin_45894245/article/details/108869963
Web服务器Apache目前一共有三种稳定的MPM(Multi-Processing Module,多线程处理模块)模式。
Prefork :进程模式
Worker :线程模式
Event : 事件模式 (2.4版本开始稳定使用)
Prefork运行模式详解:
1、Prefork MPM :Prefork MPM实现了一个非线程的、预派生的Web服务器。它在Apache启动之初,就先预派生一些子进程,然后等待连接;可以减少频繁创建和销毁进程的开销,每个子进程只有一个线程,在一个时间点内,只能处理一个请求,这是一个成熟稳定,可以兼容新老模块,也不需要担心线程安全问题,但是一个进程相对占用资源,消耗大量内存,不擅长处理高并发的场景。
最重要的是将MaxRequestWorkers设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。
注:Prefork 是基于多进程的模式
优点:因为每个进程使用独立的内存空间,所以比较安全,一个进程坏了,不会影响其他进程。
缺点:占用的内存比较大。
如果在预编译的时候没有指定MPM的模式,默认使用的是Prefork模式。
[root@localhost ~]# vim /etc/httpd/httpd.conf
如图上所示:在Apache的配置文件中,可以看出使用的是MPM的哪个模式,我的Apache在预编译的时候,使用参数让Apache三种模式都支持,但指定了使用Event模式,所以这里Event行前的#是被取消掉的!!!
2、Worker MPM:和Prefork模式相比,worker使用了多进程和多线程的混合模式,worker模式也同样会先预派生一些子进程,然后每个子进程创建一些线程,同时包括一些监听线程,每个请求过来会被分配到一个线程来服务。线程比起进程来更轻量,因为线程是通过共享父进程的内存空间,因此,内存的占用会减少一些,在高并发的场景下会比Prefork有更多可用的线程,表现会更优秀一些,另外,如果一个线程出了问题也会导致同一个进程下的线程出现问题,如果是多个线程出现问题,也只是影响Apache的一部分,而不是全部,由于用到多进程多线程,需要考虑到线程的安全了,在使用Keep-alive长连接的时候,某个线程会一直被占用,即使中间没有请求需要等待到超时才会被释放(该问题在Prefork模式下也存在)。
注:Worker MPM
优点:可以处理海量请求,而系统资源的开销小。原因:一个进程中包括多个线程,多个线程之间可以共享内存,所以占用的内存资源比较少。
缺点:不太安全,如果一个线程坏了,整个进程都要坏了,另外存在Keep-alive长连接占用资源时间过长。
如何避免进程中某个线程坏了?一个进程中所有线程完成一定数量的请求后,自动关闭,再重新打开,就可以避免内存溢出等问题。
不管是Worker模式还是Prefork模式,Apache总是试图保持一些备用的(Spare)或者是空闲的子进程(空闲的服务线程池),用于接受客户端即将到来的请求,这样客户端就不需要再等到服务前等候子进程的产生。
3、 Event MPM :event模式是在2.4版本中才稳定发布的模式,这就是Apache最新的工作模式,他和worker模式很像,不同的是在于它解决了Keep-alive长连接的时候占用线程资源被浪费的问题,在event工作模式中,会有一些专门的线程用来管理这些Keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放,这增强了在高并发场景下的请求处理。
当某个连接没有请求时,会主动关闭连接,在Worker模式下,必须要等Keep-alive超时,才可以释放。
在./configure配置编译参数的时候,可以使用 --with-mpm=prefork | worker | event 来指定编译为哪一种MPM,当然也可以用编译为三种都成 --enable-mpms-shared=all,这样在编译的时候会在modules目录下自动编译出三个MPM文件的so,然后通过修改httpd.conf配置文件更改MPM。
4、查看当前使用的是那种MPM
[root@localhost ~]# /usr/local/apache/bin/apachectl -M | grep event #可以查看到使用的是什么模式
mpm_event_module (shared)
也可以使用:/usr/local/apache/bin/apachectl -V 查看MPM ; 如下;
使用:/usr/local/apache/bin/httpd -M | grep event 和 /usr/local/apache/bin/httpd -V 和上述是一样的效果;
总结:
RHEL6/7系统自带的apache默认采用的是Prefork进程模式,在编译apache源码时,如果不用--with-mpm显式指定某种MPM,Prefork就是缺省的MPM;
HTTP 2.4 新特性:
1)MPM支持在运行时装载
指定启用:
--enable-mpms-shared=all --with-mpm=event ##把所有支持的MPM都编译出来,但启用默认的是event
2)支持event 2.2版本也支持,只不过是测试版本
3)异步读写
4)在每模块及每目录上指定日志级别
5)每请求配置;<If> <Elseif>
6)增强版的表达式分析器
7)毫秒级的keepalive timeout,使用ms指定为毫秒
8) 支持主机名的虚拟主机不在需要NameVirtualHost指令
9)支持使用自定义变量
新增一些模块:mod_proxy_fcgi(基于fcgi方式调用执行环境)
mod_ratelimit (用于做速率限定)
mod_request (对请求方法做限定)
mod_remoteip (对远端IP做限定)
对于基于IP的访问做了修改,不在使用order,allow,deny这些机制;而是统一使用require进行调整MPM模块则直接修改主配置文件中的LoadModule指定即可。
二、优化部分
1、对Prefork模块进行设置,修改apache的httpd-mpm.conf配置
[root@lamp ~]# cd /etc/httpd/extra/
[root@lamp extra]# mv /etc/httpd/extra/httpd-mpm.conf ./httpd-mpm.conf.bak
[root@lamp extra]# egrep -v "#|^$" ./httpd-mpm.conf.bak > ./httpd-mpm.conf
[root@lamp extra]#
先将http-mpm.conf 中的注释行和空行过滤掉
注释:
StartServers 5 在初始化的时候打开5个进程
MinSpareServers 5 最少有5个备用空闲进程
MaxSpareServers 10 最多10个备用空闲进程
MaxRequestWorkers 250 Apache最大的处理并发请求是250个
MaxConnectionsPerChild 0 这个一般不用,
添加:
ServerLimit 250 该参数是最大的进程数,由于Prefork模式进程和线程是一对一的,所以最大请求并发得和最大进程数相等。
针对于Prefork中参数数值的调整,还是需要根据实际情况(服务器性能,业务需求)来进行调整:
如果做5000个并发的Web,需要多少内存? 5000*2M/0.8/1024=12.2G,服务器大概需要14G——16G内存,
ServerLimit的大小,取决于你系统的资源,每个Apache进程默认大约占用2M内存,基本可以按照这个工时来计算,最大内存*80%/2M=ServerLimit (一个进程正常是1.6-1.7M,上述使用2M作为计算的)。
根据上面的描述,修改参数如下:
注释:MaxRequestsPerChild 1000 #每个子进程可以支持的请求数,累计到1000。会重启进程。存在长连接的话,一个长连接只能算一个。这可以设置为0,因为一个进程关闭,所有的线程也都关了。
额外参数:
MaxKeepAliveRequests 200 # 限制KeepAlive长链接最大处理200个请求。
目前用的MPM是Event,修改Apache配置文件,调整位Prefork:
修改为:
重新启动Apache之后发现,Apache预派生进程数变成5个:
注释:
5个预派生进程是Prefork默认的,Apache没有去读取我们修改过的http.mpm.conf文件。
在配置文件中,将该行的注释取消掉。
重启Apache查看预派生的进程数如下:
查看到httpd进程数52个,多的两个。一个是我们grep抓取时候的进程,还有一个是httpd的主进程。
一般对于数值的设定,够用就行。
如上:进程中第六列是每个进程占用我们资源大小,1536K。
[root@lamp extra]# ps -aux | grep httpd | awk '{sum += $6; n++};END{print sum/n}'
1546.46
[root@lamp extra]#
使用awk进行第六列自加。算出总量1546.46K。1M=1024K
比如:内存2G 20%的内存留给系统使用,最大可以处理多少Apache并发;
内存2G - 400M =1600M/1.5M = 1100并发数; 然后根据实际计算,修改Prefork_module参数;
watch 命令用于动态的观察Apache的最大连接数:
watch -n 1 "pgrep httpd | wc -l"
使用ab来进行测压:
[root@lamp ~]# yum install -y httpd-devel #ab是httpd-devel提供的,ab是最简单的测压工具
通过ab命令测试以及配合watch可以动态查看到进程数量的变化;等请求完成之后,进程数量不断减少至52;
2、对worker模块进行设置,修改apache的httpd-mpm.conf配置
worker比prefork内存资源使用少很多,适用于高并发,缺点就是一个线程崩掉了,整个进程就崩掉了,稳定性不如prefork。
修改Apache配置文件,将Prefork注释掉,启用worder;
重新启动Apache;
查看目前使用的MPM模块:如下
查看预派生进程数是不是变成worker默认的三个:如下
修改httpd.mpm.conf配置文件:如下(生产环境最常用的)
注释:
ServerLimit 64 最大的进程数限制
StartServers 5 最初建立的子进程
MinSpareThreads 25 最小空闲线程数
MaxSpareThreads 500 最大空闲线程数
ThreadsPerChild 150 每个进程包括150个线程数
ThreadLimit 200 一个进程下最大的线程数限制
MaxRequestWorkers 9600 表示Apache最多同时处理9600的并发请求,超过的进入队列等待;9600是64*150得到的;
此服务器配置:最多进程数:64个,最多线程数(最大并发数)64*150=9600,不可以超过64*200=12800
然后保存配置 ,重启Apache,即可生效;
案例:
如果MaxRequestsPerChild 30000 这样配置会有什么结果?
结果:一但到30000次请求 , 那150个线程都关了,会出大量闪断情况。
3、Event模式,了解以下即可;
总结:
Apache httpd 能更好的为有特殊要求的站点定制。例如,要求 更高伸缩性的站点可以选择使用线程的 MPM,即 worker 或 event; 需要可靠性或者与旧软件兼容的站点可以使用 prefork
源文地址:https://blog.csdn.net/weixin_45894245/article/details/108869963