httpd进程超多不必定是apache自己的事

本篇文章是为使用Apache+MySQL,并为Apache耗尽内存而困扰的系统管理员而写。若是您没有耐心读完本文,请参考如下步骤:mysql

1. 修改/etc/my.cnf,加上这样一行:
log-slow-queries=queries-slow.log
2. 重启MySQL
3. 酌情过上一段时间,执行mysqldumpslow命令,或直接查看datadir/queries-slow.log,从中找出执行超时的SQL语句。其中datadir是MySQL全部数据库的存放路径。
4. 根据上一步找出的SQL语句的内容,找到相应的数据表和脚本文件,查看超时缘由所在。可能的缘由有:数据量确实太大,未使用索引加快查询速度,等等。但程序没写好确定是缘由之一。
5. 根据查出的缘由酌情解决。程序员

可能有不少系统管理员都为这样的情形而困扰过:Apache进程动辄占用内存几百兆,并且剧烈浮动,变化无常,有时甚至耗掉上G内存。在访问者那里 的表现就是网站速度极不稳定,间歇性抽风,有时甚至会有5-30分钟没法打开网页。(ps:可经过此命令查看平均每一个httpd进程占用实际物理内存的大小 ps aux|grep -v grep|awk '/httpd/{sum+=$6;n++};END{print sum/n}'  单位:KB)这时候,你的上司或同事可能会急切地打来电话问:咱们的网站怎么上不去 了?咱们今天还要xxxx呢!但这时你的SSH也没法像往常同样忠实地给你一个“login:”,由于它也连不上服务器了。这个时候你的服务器在作什么 呢?你找出各类理由向他们解释以后,过上一段时间,网站可以正常访问了,你也终于SSH上了服务器(听起来系统管理员真没用),而后你会用dmesg或者 在 /var/log/messages里面发现一堆有关内存的信息,什么DMA了,HighMem了,其中会包含相似这样一行:
Out of Memory: Killed process 6760 (httpd).
它告诉你的信息是,你的服务器物理内存耗尽,也没什么好向交换区淘汰的了,只好杀掉了你的Apache的一个进程。之因此选择这个进程,基本上就是由于它占用的物理内存最多。sql

很没面子的说,我被这样的问题困扰了大半年。我曾在网上疯狂地搜索解决的办法,那些文章通常都会告诉你修改httpd.conf,把 MinSpareThreads或是MaxSpareThreads或是MaxRequestsPerChild设小一点,我尝试过各类设定,都没有明显 的效果。我甚至曾极端地经把MaxRequestsPerChild设为1,可是Apache的进程仍是会淤积,超过ServerLimit设定值,直到 耗尽内存。数据库

我曾经怀疑过是PHP内存泄漏,由于PHP官方不保证PHP的各类扩展是线程安全的,推荐使用prefork MPM而不是worker MPM.因而我也曾经把ThreadsPerChild设为1,由于这样每一个进程也就只有一个线程,在必定意义上至关于prefork MPM,可是这种作法仍是没有效果,问题依旧。安全

大约一周之前,我在检查MySQL的运行状态的时候,发现有一项Slow_queries数值很高,我敏感地认识到多是某个程序的SQL语句没有 写好,并且极可能就是这样的程序致使Apache进程淤积。而后我翻阅了MySQL手册中有关Slow query log的部分,按照那里的指示,修改/etc/my.cnf,在mysqld那一段加上以下一行:服务器

log-slow-queries=queries-slow.logide

重启MySQL。过上一段时间之后,用mysqldumpslow命令找出了执行超时的那条语句,根据那条查询的内容,我找出相应的脚本。那是一个 留言本页面,程序确实没有写好,成了垃圾广告的乐园。有人经过这个页面向数据库里面写入了超过10万条的流言,而正常的留言还不到300条。并且这个程序 里面分页的作法,竟然是查询数据表里面全部10万条数据并排序,而用到的只有区区10条。居然不使用LIMIT语句,我~@#$%^&*!后来证 实这个留言本已是废弃的了(我想也不多是正在使用的,由于每次都执行超时,已经没法使用了),就删掉了。以后,就再也没有出现过进程淤积、内存耗尽的 问题。在ThreadsPerChild=64的状况下,每一个 Apache进程的内存通常就几十兆,最多的时候也就只有200M,进程数量也不多超过六七个。网站

历经千辛万苦,终于搞定了这个问题。在此加以总结,但愿本文可以给跟我同样被程序员害惨的系统管理员们一点点帮助。spa

原题:再也不为Apache进程淤积、耗尽内存而困扰
出处:互联网线程

相关文章
相关标签/搜索