起因:
#。一台1G内存的服务器,出现MYSQL自动停止的情况。
过程:
#。查MYSQL日志:/var/log/mysql/error.log,INNODB的一个初始化错误,导致开始shutting down
#。开始错误的认为是MYSQL相关的参数设置错误,尝试调试了相关参数后,重启。
##。后来先重启起来使用,没过多久,情况重现。
##。发现出现这个情况的,一般是在用户上传大文件EXCEL导入,就出现。
##。而且出现这个情况的那一会儿,马上重启MYSQL是失败的,尝试先重启了PHP7.1-FPM,才能成功。OK,定位问题出在PHP7.1-FPM这里。
#。先从PHP程序入手调试解决问题:
##。尝试在CI3中找内存调试相关的函数库:
基准测试类(http://codeigniter.org.cn/user_guide/libraries/benchmark.html#id5)中提到“显示内存占用”,然而它的前提是 PHP 在安装时使用了 –enable-memory-limit 参数进行编译,而我们服务器基本采用APT-GET,尝试使用这个函数,没有输出。
后来直接使用PHP的memory_get_usage,可以获取当前的内容占用情况,结合ini_get(‘memory_limit’)获取当前的内存限制情况(实际上应该是可以使用ini_set设置超过该值)。
在本地XAMPP环境下再次调试出问题的EXCEL的文件上传,同时改良了PhpSpreadsheet读取EXCEL文件的方式(参考:https://www.cnblogs.com/webwei2017/articles/9094028.html),以减少内存消耗,发现本地测试没有报错。
以为已经解决问题,GIT提交,线上PULL。在线测试,发现无法上传,报内存溢出的错误:
Allowed memory size of xxx bytes exhausted at xxx:xxx (tried to allocate xxx bytes)
查看memory_limit为512MB,难道是NGINX还有另外的内存限制,找到了这些资料:
查看php-fpm开启的进程数以及每个进程的内存限制,https://www.cnblogs.com/terryguan/p/6599788.html
按第3步,查看我们服务器的php_admin_value[memory_limit]参数,发现是注销状态,猜测应该不是这个问题。
nginx+php-fpm模式php内存泄漏探究,https://blog.csdn.net/blakefez/article/details/46691171
很好的材料,用图的方式,把原理说的很明白。文中提到了几个关键的点:
PHP配置文件里面的memory_limit 这个东西,其实,它限制的只是这个“请求处理”的内存。所以,这个参数跟php-fpm进程占用的内存并没有什么关系。那为什么会有占用2G大小的php-fpm进程呢?原因是这样的:php是用c写的,所以,难免又会一些内存泄露(当PHP出现内存溢出时,相关的变量是不会销毁的)。也就是说,在“请求处理”这个过程结束后,有些变量没有被销毁,然后就导致一个php-fpm进程占用的内存越来越大。
那么,有什么办法能阻止这个问题呢?方法一:写不泄漏内存的php程序;方法二:在php-fpm配置文件中,将pm.max_requests这个参数设置小一点。这个参数的含义是:一个php-fpm子进程最多处理pm.max_requests个用户请求后,就会被销毁。当一个php-fpm进程被销毁后,它所占用的所有内存都会被回收。
方法一,显然比较难,有很多的不确定因素,同时写好成本也比较高。
#。再次TOP查看内存情况,发现问题
SSH客户端,命令top,查看内存情况,发现:
剩余内存仅剩300左右,MYSQLD就占用500MB左右,重启MYSQLD,仍然是500MB左右,这个对于小服务器来说,太浪费了,找到以下材料:
MySQL 5.6内存占用过高解决方案
https://blog.csdn.net/wulantian/article/details/41119755
解决与结论:
#。经过上面的过程,基本理解了出问题的原因,结论如下:
服务器剩余内存本来就不足300MB,部分PHP请求(EXCEL导入操作)内存溢出,导致继续压缩内存,最后一次EXCEL导入执行时,占用了所有剩余的内存,这时MYSQLD刚好要做清空和初始化innodb_buffer操作,执行过程中,发现内存没有了,初始化失败,于是开始所有的shutting down,直到全部关闭。
#。解决办法:
##。调整MYSQLD,释放更多的内存:小服务器,MYSQL的压力非常小,不需要占用这么多的内存。参考(MySQL 5.6内存占用过高解决方案,https://blog.csdn.net/wulantian/article/details/41119755),在/etc/mysql/my.cnf文件中的[mysqld]最底部,添加
performance_schema_max_table_instances=200
table_definition_cache=200
table_open_cache=128
重启mysqld(service mysql restart),TOP查看,搞定。
##。设置NGINX,及时处理掉占着内存的php-fpm(特别是溢出的):参考文中提到的nginx+php-fpm模式php内存泄漏探究,修改/etc/php/7.1/fpm/pool.d/www.conf
pm.max_requests = 1
重启php7.1-fpm(service php7.1-fpm restart)
后续与反思:
#。服务器的配置优化要考虑到程序内存溢出和占用的情况。
#。消耗大的程序的要重视内存与执行时间的调试。
#。很久没折腾服务器的优化运维,这里也有大量的内容。
转载请注明出处:IT要点网 » 小服务器(1G内存)php7.1-fpm mysql nginx的简单优化记录