解决win2003下apache的httpd.exe占用内存的问题
本文系转载:http://zhizhuofl.blog.163.com/blog/static/699147792010119114420871/
昨天又有新的情况发生。10分钟报一次内存满,无法打开论坛,远程连接到服务器一看,吓我一大跳,httpd.exe进程占用700多M内存。重启一下apache服务,发现httpd.exe从20M开始往上涨,从不释放内存,不断增加,增加到700多M后论坛打不开,内存满了。
又是一个严重问题,经过整整3个小时的google搜索,终于从google的海洋中找到了问题的所在。
这几天遇到了一个很多人都遇到过的问题,这个问题在google上有太多的人都遇到,但很少有指出最终的解决方案,大部分是解决了AcceptExfailed,但引起了内存的疯狂增加(“memoryleak”)。这几天遇到这个问题后也费了不少功夫,但没有从网上找到最根本的解决办法,幸运的是,最终探索出了一个解决方案,在这里写出来,希望能帮助后来遇到问题的难友们尽早解决问题。
遇到的问题比较曲折,大体经过是:
某天,不能访问apache的页面,检查得知,apache在疯狂写日志,而且大部分是一句话:“winnt_accept:AsynchronousAcceptExfailed”,最多的时候写到了200M以上。经各方探索,最终在apache的手册上找到了一个解决方法:
在http.conf配置中设置Win32DisableAcceptEx参数。这样做的原因是,apache在某些Windows版本上可能兼容性不足,在调用AcceptEx接收请求时可能有问题,使用上面的参数禁用后,apache会使用另一套方案替代(BSD),这种方案效率稍微低些。详见:
http://httpd.apache.org/do...
当时修改完该设置后,重启apache,测试了一段时间,感觉原来的问题确实消除了,不过当时感觉内存占用量非常明显,但测试一段时间没有问题就放过去了,直到今天下午:
今天下午发现又不能访问页面了,然后检查apache发现它已经crash了。然后打开日志发现最后一句:“Outofmemory!”--内存不足了。
然后对内存进行测试,发现一直按住F5键不停,apache的内存就不停上涨,似乎有一直吃光内存的意思,停止刷新后只能下降到500M左右了(刚启动时是20M)。如果不使用Win32DisableAcceptEx参数则明显没有这个问题,停止刷新后能回落到20M。看来是这个参数的原因。
于是从google上寻找答案,但可惜的是没有太多有价值的东西。只能看到apache的官方网站已经把这个问题列为了一个bug,甚至有些人又退回到不使用那个参数(忍受AcceptExfailed的风险?)。最后看到了一个说法,将ThreadsPerChild设为170以下就可以,可为什么是170以下呢?作者没有很多描述。于是自己探索如下,使用一个简单的页面,不停的按住F5刷新:
如果将Threadsperchild设为50,无论怎么刷新内存最多到150M左右,但不会再长了。停止刷新后,会降到55M左右;如果将ThreadsPerChild设为100,内存峰值:282M,能降到92M左右;如果将ThreadsPerChild设为550,内存峰值2G,停止后到500M左右……。
按照上述规律,基本上找到了问题的原因,因为我的配置中原来使用的是ThreadsPerChild550,这样也就是内存很可能会长到2G以上(复杂页面比简单页面耗用量大),而机器的内存设置不能支持这么大,因此应该就是这个问题了。
所以最终的解决方法就是保留Win32DisableAcceptEx的同时修改了ThreadsPerChild150。解决完成后我推测内存疯狂增长的原因:
首先,ThreadsPerChild的意思是系统启动时默认启动的等待线程数,用来等待处理客户的请求。在使用AcceptEx时内存增长不明显并且可以降回20M左右,可能是因为用户来了请求线程分配了一些资源,此时内存增长,但用户访问完成后,这些资源都释放了(这些资源很可能都和用户相关,没法留着下个用户使用,所以都释放了)。但禁用了AcceptEx后,由于apache每个线程需要处理网络事件,因此每个线程的资源需要就多了,并且处理完一个用户的请求后,有些资源不想释放,是可以对下个用户重用的,这样就留在了里面。由于我的线程数设了550(估计网上很多人遇到这个类似于“memoryleak”问题的可能也都设的比较大或者机器虚拟内存较小),这样当线程较多时就会出现达到最大内存的情况,而且这种现象给人的感觉就是有内存泄漏,因为初始时是20M,来一个请求后线程分配一些资源(暂时不释放的),这样可能就变成了21M,如果同时有10个人访问,可能等他们访问完后就变成了50M,感觉是有内存泄漏。
这样也就解释了为什么有人说设到170以下就不再出现内存不足了,可能因为他的机器这个配置比较合适。不过知道了上述的规律和一些推测,这个结论应该是根据自己机器的情况合理调配。
原来是disable了AcceptEx后引起的问题,但是又不能打开AcceptEx,只能按照文章中所述将ThreadsPerChild修改为150,问题解决。
同时希望apache官方能尽快修正这一严重BUG。