apache2三种模式
prefork MPM
prefork是比较古老而又稳定的apache模式,特点是每个进程都是单线程,在一个时间点只能处理一个连接,需要启动大量的进程来处理高并发的请求。由于是单线程进程,因而无须考虑线程安全的问题,可以使用非线程安全的库,例如mod_php。
优点是成熟稳定,缺点是比较消耗内存,而且并发支持受限于进程数量,对高并发支持稍差。
worker MPM
worker同样使用多个进程,但每个进程又拥有多个线程,每个线程处理一个连接。由于线程是轻量级的,因而具有较高的并发性,同时,多个进程又获得了一定的稳定性。worker模式特点是占用内存少,并发性比较高,缺点是必须考虑线程安全。如果使用了keep-alive方式,一个线程可能会被一直保持一个连接,但中间没有请求,直到超时。如果有多个线程被这样占据,在高并发场景下同样会出现无线程可用的情形。
event MPM
event模式是在2.4版本中才稳定发布的模式,它在worker的基础上,解决了keep-alive连接不能释放的问题。event MPM中,会有一个专门的线程来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力。
apache2 配置
查看当前使用的模式:apachectl -V | grep -i mpm
prefork MPM
mpm_prefork.conf文件内容如下:
<IfModule mpm_prefork_module>
StartServers 10 # 启动时进程数
MinSpareServers 5 # 最小空闲进程数
MaxSpareServers 10 # 最大空闲进程数
MaxRequestWorkers 100 # 最大并发进程数
MaxRequestsPerChild 10000 # 最大连接数限制
</IfModule>
各个指令的含义:
StartServers : apache2启动时创建的服务进程数量。
MinSpareServers:最小空闲进程数量,空闲进程指的是没有处理请求的进程。
MaxSpareServers : 最大空闲进程数量。
MaxRequestWorkers : 最大同时处理请求的进程数量,也是最大的同时连接数,表示了apache的最大请求并发能力,超过该数目后的请求,将排队。
MaxConnectionsPerChild : 进程生命周期内,处理的最大请求数目。达到该数目后,进程将死掉。如果设置为0,表示没有限制。该参数的意义在于,避免了可能存在的内存泄露带来的系统问题。
通过上面的介绍可以发现,prefork模式下,影响并发性能最重要的参数就是MaxRequestWorkers,它决定了apache的并发处理能力。但是这个参数不是越大越好,因为如果超出了系统硬件能力,机器会卡死。
确定合适的MaxRequestWorkers:通过top命令查看apache进程占用的资源,主要看%CPU和%MEM这两个指标,例如,每个进程的CPU占用率不超过1%,每个进程的内存占用率不超过2%,考虑内存限制,比较合适的apache进程数量为50个。
然后,逐步测试最大值。通过观测得来的CPU和内存的指标有一定的误差,一般可以适当调节这个数值,例如调到1.5或者2倍,再通过峰值场景下的机器是否卡顿来判断是继续上调还是下调。
worker MPM
<IfModule mpm_worker_module>
StartServers 20 # 启动时进程数
MinSpareThreads 25 # 最小空闲线程数
MaxSpareThreads 75 # 最大空闲线程数
ThreadLimit 64 # 每个进程可以启动的线程数量上限值
ThreadsPerChild 25 # 每个进程可以启动的线程数量
MaxRequestWorkers 400 # 线程数量最大值
MaxRequestsPerChild 0 # 最大连接数限制
</IfModule>
配置文件和前面的prefork有一些变动,但是基本的概念差不多。原来以进程为单位的概念转变成了以线程为单位的概念,例如MinSpareServers转变为MinSpareThreads,多了一个ThreadsPerChild,表示每个进程可以有的线程数量,其上限值为ThreadLimit。
注意,修改了ThreadsPerChild后可以通过apache2 restart来生效,但是修改了ThreadLimit只能先stop,然后start。
在worker模式中,MaxRequestWorkers转变为了线程数量,比起prefork模式下可以有比较大的增长,通常可以有好几倍的差别。这是worker模式相比于prefork的优势,worker拥有比较多的处理线程,可以同时保持大量的连接,峰值应对能力比较强。尽管出于CPU或者数据库的原因,这些连接不能在第一时间内被处理,可能产生较大延迟。
确定worker模式的参数:有两个参数比较重要,一是ThreadsPerChild,这个表示每个进程的线程数目,一般采用默认值即可,如果是并发量比较大,可以考虑加大这个值。另外一个就是MaxRequestWorkers了,在workers模式下,任务处理的负载会分发给php-fpm来处理,所以apache主要承担了建立和保持连接的任务,并不消耗太多资源,因而在理论上,MaxRequestWorkers可以非常大。
但是从实用体验来看,如果MaxRequestWorkers远超系统的请求处理能力,会有大量的请求排队,因而产生比较大的延迟,这个时候的体验并不好。所以这个参数一开始可以稍大,例如可以设置为prefork模式下的几倍,然后根据线上峰值延迟不断调整这个数值。MaxRequestWorkers必须是ThreadsPerChild的整数倍,否则apache会提示调整到一个相近的值。MaxRequestWorkers也有最大值限制,即ServerLimit乘以ThreadsPerChild。默认ServerLimit值是16,必要时可以显式声明加大这个值。
event MPM
event模式下的参数意义和worker模式完全一样,按照上面的策略来调整即可。
event相比于worker的优势是,它解决了worker模式下长连接线程的阻塞问题。
值得一提的是,worker/event模式的请求处理模式,已经和nginx的libevent模式相同了。在mod_php模式下,每个apache进程都需要直接执行php,所以很容易达到系统资源限制。但是在php-fpm模式下,apache只负责建立连接,然后把请求传递给php-fpm来处理。这样,apache可以保持大量的连接,请求处理能力取决于php服务器的性能。由于event是明显优于worker的,所以在apache2.4及后续版本中,一般优先选择event模式。
常见问题
查看apache的error日志,可以发现许多系统运行中的问题。
[mpm_prefork:error] [pid 1134] AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting
进程或者线程数目达到了MaxRequestWorkers,可以考虑增加这个值,当然,先考虑增加硬件。
[mpm_event:error] [pid 7555:tid 140058436118400] AH00485: scoreboard is full, not at MaxRequestWorkers
这个问题好像是apache2自带的bug,我们无力解决。好在这个问题一般只会影响单个线程,所以暂时可以忍。
一些系统状态指标
ps命令
查看当前系统apache和php进程、线程数目,下面的命令适用于ubuntu系统。
查看apache进程:ps aux | grep apache
查看apache进程数目:ps aux | grep apache | wc -l
worker/event模式下,查看线程数目:ps -eLf | grep apache | wc -l
查看php-fpm进程数:ps aux | grep php-fpm | wc -l
apache性能调试是一个比较复杂的问题。除了apache本身配置、PHP配置,还会涉及到数据库。后台的难点就在于如何应对高并发、大流量的请求,这往往不是单个点可以解决的,需要系统各个模块来协调。
修改Linux下Apache的最大连接数
Apache的最大连接数,默认为256个。
修改apache的最大连接数,方法如下:
一:先修改usr/local/apache/conf/httpd.conf文件。
将“#Include conf/extra/httpd-mpm.conf”前面的 # 去掉,保存。
二:再修改./apache/conf/extra/httpd-mpm.conf文件。
找到<IfModule mpm_winnt_module>
ThreadsPerChild 150 #推荐设置小型网站=1000 中型网站=1000~2000 大型网站=2000~3500
MaxRequestsPerChild 0 #推荐设置:小=10000 中或大=20000~100000
</IfModule>
查看apache当前工作模式:httpd -V或者apachectl -V | grep -i mpm
<IfModule mpm_prefork_module>
StartServers 5 #推荐设置:小=默认 中=20~50 大=50~100
MinSpareServers 5 #推荐设置:与StartServers保持一致
MaxSpareServers 10 #推荐设置:小=20 中=30~80 大=80~120
ServerLimit 1000
MaxRequestWorkers 150 #推荐设置:小=500 中=500~1500 大型=1500~3000
MaxConnectionsPerChild 0 #推荐设置:小=10000 中或大=10000~500000
在apache2.3.13以前版本MaxRequestWorkers被称为MaxClients
注意:1、一定添加ServerLimit,并且要在MaxClients前面,且数值要比MaxClient的值大;
2、重启apache,仅仅/bin/apachectl restart无效,需要先apachectl stop 然后再apachectl start
对apache中并发控制数prefork理解和调优
一个apache有linux下的并发不是很高的,大约到3K的样子,普通的服务器都会不同程度的出现问题.apache有关并发控制主要是 prefork和worker二个其中一个来控制.我们可以使用httpd -l来确定当前使用的MPM是prefork.c,还是Worker.c.下面是apache中有关prefork的配置.下面是优化过的参数.
<IfModule prefork.c>
#有这个参数就不必像apache1一样修改源码才能修改256客户数的限制,听讲要放到最前面才会生效,2000是这个参数的最大值
ServerLimit 2000
#指定服务器启动时建立的子进程数量,prefork默认为5。
StartServers 25
#指定空闲子进程的最小数量,默认为5。如果当前空闲子进程数少于MinSpareServers ,那么Apache将以最大每秒一个的速度产生新的子进程。此参数不要设的太大。
MinSpareServers 25
#设置空闲子进程的最大数量,默认为10。如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程将杀死多余的子进程。此参数不要设的太大。如果你将该指令的值设置为比MinSpareServers小,Apache将会自动将其修改成"MinSpareServers+1"。
MaxSpareServers 50
#限定同一时间客户端最大接入请求的数量(单个进程并发线程数),默认为256。任何超过MaxClients限制的请求都将进入等候队列,一旦一个链接被释放,队列中的请求将得到服务。要增大这个值,你必须同时增大ServerLimit 。
MaxClients 2000
#每个子进程在其生存期内允许伺服的最大请求数量,默认为10000.到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为"0",子进程将永远不会结束。
MaxRequestsPerChild 10000
</IfModule>
将MaxRequestsPerChild设置成非零值有两个好处:
1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。
2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。
工作方式:一个单独的控制进程(父进程)负责产生子进程,这些子进程用于监听请求并作出应答。Apache总是试图保持一些备用的 (spare)或者是空闲的子进程用于迎接即将到来的请求。这样客户端就不需要在得到服务前等候子进程的产生。在Unix系统中,父进程通常以root身份运行以便邦定80端口,而 Apache产生的子进程通常以一个低特权的用户运行。User和Group指令用于设置子进程的低特权用户。运行子进程的用户必须要对它所服务的内容有读取的权限,但是对服务内容之外的其他资源必须拥有尽可能少的权限。
我们调优常常要查看httpd进程数(即prefork模式下Apache能够处理的并发请求数):#ps -ef | grep httpd | wc -l
出现的结果,就是当前Apache能够处理的多少个并发请求,这个值Apache根据负载情况自动调.
查看Apache的并发请求数及其TCP连接状态:
状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放 处理完毕,等待超时结束
LAST_ACK:等待所有分组死掉
#mpm_worker模块
<IfModule mpm_worker_module>
StartServers 2 #推荐设置:小=默认 中=3~5 大=5~10
ServerLimit 1000
MaxRequestWorkers 150 #推荐设置:小=500 中=500~1500 大型=1500~3000
MinSpareThreads 25 #推荐设置:小=默认 中=50~100 大=100~200
MaxSpareThreads 75 #推荐设置:小=默认 中=80~160 大=200~400
ThreadsPerChild 25 #推荐设置:小=默认 中=50~100 大型=100~200
MaxConnectionsPerChild 0 #推荐设置:小=10000 中或大=10000~50000(此外,还需额外设置ServerLimit参数,ServerLimit必须大于等于MaxClients/ThreadsPerChild 的值。)
</IfModule>
说明:非原创,忘记文章链接了