httpd进程超多不一定是apache本身的事

blogdaren 2014-12-22 抢沙发 1469人次

不再为Apache进程淤积、耗尽内存而困扰

本篇文章是为使用Apache+MySQL,并为Apache耗尽内存而困扰的系统管理员而写。请参考以下步骤:

  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分钟无法打开网页。这时候,你的上司或同事可能会急切地打来电话问:我们的网站怎么上不去了?我们今天还要xxxx呢!但这时你的SSH也无法像往常一样忠实地给你一个“login:”,因为它也连不上服务器了。这个时候你的服务器在做什么呢?你找出各种理由向他们解释之后,过上一段时间,网站能够正常访问了,你也终于SSH上了服务器(听起来系统管理员真没用),然后你会用dmesg或者在/var/log/messages里面发现一堆有关内存的信息,什么DMA了,HighMem了,其中会包含类似这样一行:

Out of Memory: Killed process 6760 (httpd).

它告诉你的信息是:你的服务器物理内存耗尽,也没什么好向交换区淘汰的了,只好杀掉了你的Apache的一个进程。之所以选择这个进程,基本上就是因为它占用的物理内存最多。

在网上疯狂地搜索解决的办法一般都会告诉你修改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.log

重启MySQL。过上一段时间以后,用mysqldumpslow命令找出了执行超时的那条语句。

版权声明:除非注明,本文由( blogdaren )原创,转载请保留文章出处。

本文链接:httpd进程超多不一定是apache本身的事

发表评论:

您的昵称:
电子邮件:
个人主页: