目前apache的主流工作模式MPM模式。MPM是Multi-Processing-Modules的简称,意思是多道处理模块。MPM模块有不同的种类。现在用的比较多的MPM种类主要是prefork和worker。prefork的工作方式是多个进程工作,每个进程会在处理一定数量的请求后结束(这个数量可能是无穷),没有线程的概念。worker被看作apache未来的主流工作模式,它是一种多进程与多线程混合的模式。
最近发现一个比较奇怪的现象,某台以prefork模式工作的服务器的内存使用率在每次重启apache之后会不停的上涨,直到swap用完,直到死机。后来查出来是因为apache使用的某一些脚本存在内存泄露的代码段。而apache启动的调用这些代码段的进程的处理请求数被设置为无穷。也就是说这些进程只有在apache重启(stop-start模式)或者服务器(指的是机器)重启的情况下才会被kill,否则将一直运行下去,直到耗尽系统的最后一点资源(主要是内存)。
问题貌似已经解决了。但是,还有点不对,就是为什么有将近4G的可用空间(内存2G加上swap2G,除去操作系统部分),资源还是很快就耗尽了?虽然进程在每处理一个请求的情况下都会吃掉一点内存,但是在看了内存泄露的那段代码后发现每次处理泄露的内存也不过2K左右。要消耗掉3G的空间,需要至少15.7w次请求。但是目前的手机统计平台上一天的点击量也不过5w。其实top命令下就能看出来,每个httpd进程的内存使用率有2.4%,3.2%等等。对于一个2G内存的服务器,一个进程2%就等于是40M。仅仅一个普通的请求,没有post参数的,没有大规模数据库查询的,怎么会用这么多内存?httpd的进程在被apache的主控进程创建的时候,会预先加载一些包,这些包是在apache配置文件里设置的。然后发现在apache加载的包目录下,有一个很大的包,是用来根据手机号查找手机卡的信息的。去掉这个包之后,每个httpd的进程使用内存就正常了。
总结有两点:
1、MaxRequestsPerChild不能设置为0,最好设置为一个相对不大的数字,防止httpd进程有意外的内存泄露(当然,也不建议设置为1,否则apache就会不停的fork新的进程了,cpu的资源也就过多消耗了);
2、不要加载过多的包,尤其是比较大的包。如果费用不可,最好能够用数据库来存储包里的一些静态信息。