Apache性能调优
环境:
Apache 2.4
1、选择合适的MPM(Multi -Processing Modules,多处理模块)
Unix/Linux平台,有3中PMP:event,prefork及worker。在全部平台中,MPM都可以构建为静态模块。在构建时选择一种MPM,链接到服务器中。如果要改变MPM,必须重新构建。要求更高伸缩性的站点可以选择使用线程的MPM,即worker或event;要求可靠性或者与旧软件兼容的站点可以使用 prefork。
查看当前服务器使用的是哪种MPM
# httpd -l
Compiled in modules:
core.c
prefork.c
http_core.c
mod_so.c
如上,根据带背景色内容可推断出来使用的prefork MPM
prefork
实现非线程、预派生的web服务器。每个服务器进程响应进入的请求,父进程处理服务器池大小。适合需要兼容非线程安全的类库的站点。因为使用的是进程,所以,如果某个请求出现故障,不会影响其它请求,用于隔离每个请求的最好的MPM。
该MPM自我调节性强,极少需要调整其配置指令。最重要的是,MaxRequestWorkers要足够大,以处理尽可能多的请求,但同时也不能太大,确保有足够的物理内存来处理请求。
工作原理
单个控制进程负责启动子进程,子进程负责监听连接请求并在请求到达时进行除处理。Apache httpd总是尽量保持空闲,为处理进入的请求做好准备。按这种方式,客户端请求被处理之前,客户端无需等待服务器派生一个新的子进程。
为了绑定到80端口,Unix下父进程通常以root身份启动,子进程则以更少权限的用户身份,由Apache httpd启动。User和Group指令用于设置Apache httpd子进程的权限。
当遇到极大的并发问题时,该MPM使用mpm-accept mutex来序列化即将到达连接的访问。可通过Mutex进行配置该mutext的配置。
参考连接:https://httpd.apache.org/docs/2.4/en/mod/prefork.html
worker
实现多进程,多线程混合服务器。相比基于进程的服务器,worker使用线程服务器请求,可处理大量请求,同时消耗更少的内存。同时,拥有多进程处理方式,让其仍拥有有基于进程服务器的稳定性。
用于控制MPM最重要的指令为ThreadsPerChild和MaxRequestWorkers,其中,ThreadsPerChild控制每个子进程使用的线程数量,MaxRequestWorkers控制线程的最大总数
工作原理
同prefork,单个控制进程负责启动子进程,每个子进程创建由ThreadsPerChild指定的固定数量的线程,以及用于负责监听连接请求,并在请求到达时将其传递给服务器线程的监听线程。
参考连接:https://httpd.apache.org/docs/2.4/en/mod/worker.html
event
基于worker,利用主线程来处理新请求,以便允许更多的并发请求。单个控制进程(父进程)负责启动子进程。每个子进程创建一个由ThreadsPerChild指定的固定数量的服务器线程和一个监听线程,监听连接,当请求到达时,传递给worker线程进行处理。可在编译脚本时,使用--with-mpm=event选项来使用event MPM:./configure --with-mpm=event,其它MPM以此类推,不再赘述。
工作原理:
该MPM尽力弥补HTTP中的“keep alvie”问题。客户端完成第一次请求后,保持连接为open,再次发送请求时,使用相同的socket,这样在建立TCP连接时节约了极大的开销。然而,Apache HTTP服务器通常保持整个子进程、线程等待来子客户端的数据,这给服务器自身带来了不利。为了解决这个问题,针对每个进程,MPM使用一个专用的监听线程来处理监听socket。
这种模式下,不再需要mpm-accept Mutex,单个进程或线程可处理的总的连接数由AsyncRequestWorkerFactor指定
参考连接:https://httpd.apache.org/docs/2.4/en/mod/event.html
2、优化prefork
Apache httpd自我调节性强,所以大多数站点不需要调整其默认值。如果有需要可以调整其配置如下:
# vim /usr/local/apache/conf/extra/httpd-mpm.conf
……
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 250
MaxConnectionsPerChild 0
说明:
StartServers: Apache服务器启动时建立的初始服务器子进程数,由于进程数量根据负载动态控制的,所以很少需要调整该参数的值。
MinSpareServers:空闲服务器子进程的最小数,所谓空闲服务器子进程是指没有正在处理请求的子进程。如果当前空闲子进程数少于MinSpareServers ,那么Apache将创建新的子进程:创建一个,等待1s,然后创建2个,等待1秒,接着创建4个……,直到每秒创建32个子进程。当满足MinSpareServers设置时停止创建。只有在非常繁忙的机器上才需要调整这个参数。将此参数设的太大通常是一个坏主意。
MaxSpareServers:空闲服务器子进程的最大数,如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程将会杀死多余的子进程。只有在非常繁忙的机器上才需要调整这个参数,将此参数设的太大通常是一个坏主意,如果将该指令的值设置为同MinSpareServers相等或者比其小,Apache将会自动将其修改成”MinSpareServers+1″。
MaxRequestWorkers:可同时处理的最大请求数,超过MaxRequestWorkers限制的连接将要排队,排队的数量可达到基于ListenBacklog指令的某个数,一旦某个请求结束后,子进程变获得自由,开始处理下一个连接。针对非线程服务器,比如prefork,MaxRequestWorkers同时也是同一时刻,允许的最大子进程数。针对线程服务器,比如event或wroker,该参数限制了服务器可获得的最大线程总数,默认值为ServerLimit x ThreadsPerChild。如果要增加它的值,则都必须提升ServerLimit。
2.3.13版本以前,MaxRequestWorkers也叫MaxClients。老的名字依旧是兼容的。
如果服务器内存较小,可能需要减少MaxRequestWorkers防止抖动(反复交换内存到磁盘)。关于更多进程调优信息参考performance hints文档。
附:查看Apache进程数
# ps -ef|grep httpd|wc -l
21
MaxConnectionsPerChild:每个服务器子进程被终止前可处理的最大连接数(每个进程在处理了指定次数的连接,子进程将会被父进程终止,这时候子进程占用的内存就会释放),设置为0表示无限制,即不终止进程。内存较大的服务器可以设置为0(不推荐)或较大的数字。内存较小的服务器可以设置比较小的值,以防内存溢出,还可以在服务器负载下降的时侯会自动减少子进程数。一般情况下,如果你发现服务器的内存直线上升,建议修改该参数试试
注:original文件夹是配置文件的源文件备份,而真正要配置的是conf目录下的httpd.conf文件以及extra目录的额外扩展配置。
https://httpd.apache.org/docs/2.4/en/mod/mpm_common.html
3、优化worker
# vim /usr/local/apache/conf/extra/ httpd-mpm.conf
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
ServerLimit:对活动子进程数的硬限制(hard limit),值必须大于等于MaxConnectionsPerChild /MaxRequestWorkers
对于prefork MPM, ServerLimit设置整个Apache httpd生命周期内,MaxRequestWorker的最大可配置值。对于worker和event MPM,结合ThreadLimit设置MaxRequestWorkers的最大可配置
需要注意的是,如果ServerLimit设置的值远高于实际需要的值,将分配额外的共享内存。如果ServerLimit和MaxRequestWorkers设置的值大于服务器处理能力,那么可能会导致服务器无法启动或者不稳定。
针对prefork MPM,如果需要设置MaxRequestWorkers值高于256,那么需要用到该指令,不要设置该参数的值大于MaxRequestWorkers
针对worker和event MPM,如果MaxRequestWorkers和ThreadsPerChild设置要求多余16个服务器进程(默认)时使用该选项。不要设置该参数的值大于MaxRequestWorkers和ThreadsPerChild设置要求的服务器进程数(MaxRequestWorkers = ServerLimit x ThreadsPerChild)。
注意:Apache编译时,内部有一个硬限制ServerLimit 20000(针对prefork MPM 200000)。如果需要增加超过硬限制的值,需要修改源文件中的MAX_SERVER_LIMIT并重新构建服务器
ThreadLimit:在整个Apache httpd进程生命周期内,为ThreadsPerChild设置最大配置值,对服务器线程数量的硬限制,必须大于等于ThreadsPerChild,如果比ThreadsPerChild设置的值高很多,将会分配额外未使用的内存;如果ThreadLimit和ThreadsPerChild设置的值大于服务器处理能力,那么可能会导致服务器无法启动或者不稳定。
针对mpm_winnt,默认值为1920,其它64
注意:Apache在编译时,内部有一个硬限制ThreadLimit 20000(对于event,ThreadLimit 100000,对于mpm_winnt,15000),如果想增加超过该硬限制,则需在源文件中修改MAX_THREAD_LIMIT,并重新构建服务器。
注意:要使上述两个参数配置(ThreadLimit和ServerLimit),生效需要完全停止服务器,然后重启服务器
StartServers:同prefork,Apache服务器启动时建立的初始服务器子进程数,由于进程数量根据负载动态控制的,所以很少需要调整该参数的值。
MinSpareThreads:空闲服务器线程的最小数。如果当前服务器空闲线程数少于MinSpareThreads,那么Apache将创建新的子进程,直到线程数大于该数值。
MaxSpareThreads:空闲服务器线程的最大数,如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程将会杀死多余的子进程,直到空闲线程数小于该值。
ThreadsPerChild:每个子进程创建的线程数。子进程在启动时创建这些线程,且不再创建新的线程。
MaxRequestWorkers:可同时处理的最大请求数,超过MaxRequestWorkers限制的连接将要排队,数量可达到基于ListenBacklog指令的某个数,一旦某个请求结束后,子进程变获得自由,开始处理下一个连接。针对线程服务器,比如event或wroker,该参数限制了服务器可获得的最大线程总数,默认值为ServerLimit x ThreadsPerChild。如果要增加它的值,则都必须提升ServerLimit。
2.3.13版本以前,MaxRequestWorkers也叫MaxClients。老的名字依旧是支持的。
测试时,可以通过查看日志文件/var/log/apache2/error.log,如果发现如下内容,就应该增大MaxClients了:
[error] server reached MaxClients setting,consider raising the MaxClients setting
MaxConnectionsPerChild:同prefork,每个服务器子进程自动终止前可处理的最大连接数(每个进程在处理了指定次数的连接,子进程将会被父进程终止,这时候子进程占用的内存就会释放),设置为0表示无限制,即不终止进程。内存较大的服务器可以设置为0(不推荐)或较大的数字。内存较小的服务器可以设置比较小的值,以防内存溢出,还可以在服务器负载下降的时侯会自动减少子进程数。一般情况下,如果你发现服务器的内存直线上升,建议修改该参数试试
https://httpd.apache.org/docs/2.4/en/mod/mpm_common.html
4、优化event
同worker
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
参考连接:https://httpd.apache.org/docs/2.4/en/mod/mpm_common.html
5、通用配置优化
硬件和操作系统
影响web服务器性能最大的硬件问题是RAM。web服务器从不应该有交换(swap),因为交换会增加每个请求的延迟,使得响应时间超过用户可接受范围,这可能会导致用户终止操作,重新发起请求,进而进一步增加负载。除此之外,还和CPU,网卡和硬盘相关。
主机名和DNS查找
Apache 1.3以前,HostnameLookups默认为On。这会增加每个请求的延时,因为它要求在每个请求完成之前,进行DNS查找。Apache 1.3中,默认关闭Off。如果需要把日志文件中的地方解析为主机名,使用apache自带的logresolve程序或者其它可用的日志报告包。
注:配置文件installation_dir/conf/extra/httpd-default.conf
建议在其它机器上处理这类日志,而不是在web生产服务器上,这样做是为了不影响服务器性能
如果使用任意Allow from domain或者Deny from domain指令(比如,使用hostname或者domain name,而非IP地址),那么将进行两次DNS查找(一个方向的,携带一个转发的查找来保证反向查找不被欺骗)。为了最佳性能,使用这些指令时,尽可能的使用IP地址,而不是名字。
注意,可以在一个结点比如“”内处理这些指令,这种情况下,DNS查找仅仅在匹配标准的请求上执行,例子,除了.html或.cgi文件,禁用dns查找
HostnameLookups off
HostnameLookups on
KeepAlive
keepAlvie开启(默认值)时,客户端完成第一次请求后,保持连接为open,再次发送请求时,使用相同的socket,这样在建立TCP连接时节约了极大的开销,所以,一般情况下,图片较多的网站建议值为On
配置文件installation_dir/conf/extra/httpd-default.conf
KeepAliveTimeout
相同连接上,等待相同客户端的下一次请求的时间(单位:秒),超过该时间则会关闭旧的连接,并新建连接。
当使用keep-alives时,子进程、线程将在已打开的连接上忙碌着等待更多请求,但是啥也不做,浪费服务器资源,为减少这种影响,默认设置KeepAliveTimeout为5s。这是关于网络带宽和服务器资源的权衡。绝不能把该参数的值提升至60s,这样会丢失(参数带来的)大部分的好处。
配置文件installation_dir/conf/extra/httpd-default.conf
FollowSymLinks and SymLinksIfOwnerMatch
配置文件:installation_dir/conf/http.conf
不管在URL-space的任何位置,没有指定Options FollowSymLinks
,或者指定
Options SymLinksIfOwnerMatch
,
Apache
将需要发起额外的系统调用来检查符号链接
(
每个文件名组成都执行一个额外调用
)
。
例:
DocumentRoot"/www/htdocs"
<</span>Directory"/">
OptionsSymLinksIfOwnerMatch
</</span>Directory>
假如发起请求的URI为/index.html,那么Apache将对/www,/www/htdocs,/www/htdocs/index.html执行lstat(2)函数,因为不会缓存lstat的结果,所以,每个请求都会重复执行lstat(2).如果是/testdir/index.html呢?个人理解,外加/www/htdocs/testdir /www/htdocs/testdir/index.html
如果真的想要检查符号链接的安全性,这样如下:
DocumentRoot"/www/htdocs"
<</span>Directory"/">
OptionsFollowSymLinks
</</span>Directory>
<</span>Directory"/www/htdocs">
Options-FollowSymLinks+SymLinksIfOwnerMatch
</</span>Directory>
这样可以避免对DocumentRoot路径做额外的检查。注意,如果DocumentRoot之外还有别名(Alias)或(RewriteRule)路径,则需要添加相似的结点结点(section),为了更高的运行性能,应放弃符号链接保护,在所有地方都设置FollowSymLinks,并且从不使用SymLinksIfOwnerMatch。
AllowOverride
不管在你URL-space中的任何位置,允许重写(override)(典型的.htaccess文件),对文件名的每个组成部分,Apache将尝试打开.htaccess文件,例如
DocumentRoot"/www/htdocs"
<</span>Directory"/">
AllowOverride all
</</span>Directory>
请求URI为/index.html
,Apache将尝试打开/.htaccess
, /www/.htaccess
,和 /www/htdocs/.htaccess
.解决方案,类似前面的Options FollowSymLinks
案例,把
all
设置为
None
。为了更高的性能,每个地方都使用AllowOverride None
。
尽量减少不用的模块
参考链接:https://httpd.apache.org/docs/2.4/zh-cn/misc/perf-tuning.html
启用deflate
这个模块允许服务器的返回的内容通过网络传输给客户端之前先进行压缩。
参考资料:https://httpd.apache.org/docs/2.4/en/mod/mod_deflate.html
注:一般情况下,不要对图片、PDF和mp3等文件进行压缩,这些文件的压缩比太低,很费资源