Apache优化:更改MPM模式

偶然发现httpd占用了大量内存,查阅资料发现Apache默认运行在Prefork模式,该模式优点是兼容性好,也不需要担心线程安全问题,但是一个进程相对占用资源,消耗大量内存,不擅长处理高并发的场景,多个请求可能导致需要使用的内存超出物理内存的大小。所以现在已经不常用这个模式了。遂查找资料并更换MPM模式。

三种模式

在切换之前需要找到自己的php版本以及当前所处模式。Apache目前一共有三种稳定的MPM(Multi-Processing Module,多进程处理模块)模式:Prefork(进程模式)、Worker(线程模式)、Event(事件模式,2.4版本后开始稳定)。其中httpd-2.2的event模式仍然为测试使用的模型,而httpd-2.4的event模式则可在生产环境中使用。
推荐使用httpd -V命令查看

httpd -v

Server version及版本,Server MPM及运行模式

Prefork

Prefork模式在Apache启动之初,就先预派生一些子进程,然后等待连接;可以减少频繁创建和销毁进程的开销,每个子进程只有一个线程,在一个时间点内,一个线程只能处理一个请求。

Prefork运行原理

优点:成熟稳定,兼容所有新老模块。同时,不需要担心线程安全的问题。(我们常用的mod_php,PHP的拓展不需要支持线程安全)

缺点:一个进程相对占用更多的系统资源,消耗更多的内存。而且,它并不擅长处理高并发请求,在这种场景下,它会将请求放进队列中,一直等到有可用进程,请求才会被处理。

Worker

Worker模式使用了多进程和多线程的混合模式,Worker模式也同样会先预派生一些子进程,然后每个子进程创建一些线程,同时包括一个监听线程,每个请求会被分配到一个线程来服务。线程比起进程会更轻量,因为线程是通过共享父进程的内存空间,因此,内存的占用会减少一些。
但是如果一个线程出现了问题也会导致同一进程下的线程出现问题,需要考虑到线程的安全;在使用keep-alive长连接的时候,某个线程会一直被占用,即使中间没有请求,需要等待到超时才会被释放,如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用。

注:keep-alive的长连接方式,是为了让下一次的socket通信复用之前创建的连接,从而,减少连接的创建和销毁的系统开销。保持连接,会让某个进程或者线程一直处于等待状态,即使没有数据过来。

Worker运行原理

优点:占据更少的内存,高并发下表现更优秀。

缺点:不太安全。如果一个线程坏了。 整个进程都要坏了。另外存在keep-alive长连接占用资源时间过长。

Event

Event模式是在2.4版本中才可以稳定运行。这是Apache最新的工作模式,它和worker模式很像,不同的是在于它解决了keep-alive长连接的时候占用线程资源被浪费的问题,在event工作模式中,会有一些专门的线程用来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放。这增强了在高并发场景下的请求处理。当某个连接没有请求时,会主动关闭连接。

Event运行原理

修改MPM模式

httpd2.2

httpd2.2不支持同时编译多个MPM模块,只能在编译时选定要使用哪个,为此rpm包提供了三个应用程序文件:httpd(prefork), httpd.worker, httpd.event,分别用于实现对不同的MPM机制的支持;默认使用的模块为/usr/sbin/httpd,其为prefork的MPM模块。

如果要更改MPM,直接修改配置文件/etc/sysconfig/httpd

HTTPD=/usr/sbin/httpd.{worker,event}

修改后重启服务service httpd restart,此时可通过httpd -Vps aux | grep httpdhtttpd -M | grep mpm查看是否更换成功。

httpd2.4

httpd2.4支持动态编译多个MPM模块,如果要更换MPM,修改配置文件 /etc/httpd/conf.modules.d/00-pmp.conf
将原模式语句注释掉,并将想要启用的模式语句取消注释:

# Select the MPM module which should be used by uncommenting exactly
# one of the following LoadModule lines:

# prefork MPM: Implements a non-threaded, pre-forking web server
# See: http://httpd.apache.org/docs/2.4/mod/prefork.html
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

# worker MPM: Multi-Processing Module implementing a hybrid
# multi-threaded multi-process web server
# See: http://httpd.apache.org/docs/2.4/mod/worker.html
LoadModule mpm_worker_module modules/mod_mpm_worker.so

# event MPM: A variant of the worker MPM with the goal of consuming
# threads only for connections with active processing
# See: http://httpd.apache.org/docs/2.4/mod/event.html
#LoadModule mpm_event_module modules/mod_mpm_event.so

修改后重启服务systemctl restart httpd.service,此时可通过httpd -Vps aux | grep httpdhtttpd -M | grep mpm查看是否更换成功。

优化参数配置

work

配置文件 httpd.conf 中 work 的参数配置项:

<IfModule worker.c> 
ThreadLimit         100 
ServerLimit         256 
StartServers         8 
MaxClients         1200 
MinSpareThreads     100 
MaxSpareThreads     300 
ThreadsPerChild     100 
MaxRequestsPerChild  0 
</IfModule> 

关键的问题出现在 MaxRequestsPerChild 参数。MaxRequestsPerChild这个指令设定一个独立的子进程将能处理的请求数量。
在处理“MaxRequestsPerChild 数字”个请求之后,子进程将会被父进程终止,这时候子进程占用的内存就会释放,如果再有访问请求,父进程会重新产生子进程进行处理。
如果MaxRequestsPerChild缺省设为0(无限)可以使每个子进程处理更多的请求,不会因为不断终止、启动子进程降低访问效率。
但如果占用了200~300M内存,即使负载下来时占用的内存也不会减少。内存较大的服务器可以设置为0或较大的数字。内存较小的服务器不妨设置成30、50、100,以防内存溢出。
php2.4.6有所不同
留个坑以后填,或许换nginx就不填了。。

文章作者: Rainmo
文章链接: https://www.rainmos.com/apache-mpm/
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 4.0 许可协议。转载请注明来自 rainmos.com
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇