最近上线某台虚拟机三五次就会挂掉。通过业务日志,基本上发现每一个错误都来自于某个请求。因此,对该请求进行了调查。1.首先确认罪魁祸首:执行请求前虚拟机内存和python进程占用的资源:执行一次请求后的资源占用:服务执行过程中python占用的资源cpu会增加,但是request完成后cpu可以恢复到执行前的水平;而VIRT、RES、内存的比值则明显增加,执行完毕后并没有下降。多次执行,内存使用量累积增加。由此可以推断,罪魁祸首就是这个请求,很可能是内存泄漏导致的。2.python内存泄露的工具https://zhmin.github.io/2018/12/22/python-meomory-leak/通过在网上的一系列搜索,了解到python内存泄露的排查工具有:objgraph、pympler、guppyobjgraph可以查看对象被引用的次数,也可以查看对象调用图。这里主要用到的方法:show_most_common_types()show_growth()个人觉得show_growth比较好写,可以看到增量数据。pymplerpympler工具可以轻松查看内存使用情况guppyguppy可以查看堆内存的具体使用情况,哪些对象占用了多少内存3、代码定位,先写一个记录对象引用数的方法importosimportobjgraphdefobj_graph_stat(mark=''):file_path=r'D:\obj_graph.txt'如果不是os.path.exists(file_path):file=open(file_path,'w')file.close()file=open(file_path,'a')文件。写(f'******************{str(now_datetime())}-{mark}********************\n')objgraph.show_most_common_types(limit=20,file=file)file.write(f'-'*20)file.write('\n')#返回堆内存详细信息#heap=hp.heap()#byvia返回对象的引用,heap[0]是内存消耗最大的对象#references=heap[0].byvia#file.write(str(references))file.write('\n\n')file.close()在可疑代码前后执行此方法。通过执行前后对比,发现对list、dict等对象的引用明显增加。然后阅读代码,逐步缩小范围,对比前后可疑代码段,确定最小范围:同时对象引用的对比也证明了这一点,如上图所示。这段代码是基于matplotlib.pyplot画图的,对代码的主题影响不大。我们先把这段代码注释掉,再执行一遍,看看对象前后的引用数。通过对比,发现对象引用的数量是正常的!!!服务器部署执行后,对比top信息,执行前:执行过程中,执行完成后,内存恢复到执行前的水平,问题解决!4、追根究底,抓到真凶后,我们总是好奇,想知道真相。通过度娘发现:Python循环绘图时内存泄露的问题:http://www.biexiaoyu1994.com/%E4%BB%A3%E7%A0%81%E8%B8%A9%E5%9D%91/2019/06/13/python_plot_mem_leak/matplotlib绘图内存爆裂:https://blog.csdn.net/quanshengxixin/article/details/68953314matplotlib内存溢出错误:https://blog.csdn.net/mym_74/article/详情/102887252使用matplotlib画图并保存到文件。由于内存中的图像没有及时清除,导致内存爆炸,系统崩溃。pyplot是一个模块,它收集允许以功能方式使用matplotlib的函数。我在这里假设pyplot已被导入为“importmatplotlib.pyplotasplt”。在这种情况下,可以使用三种不同的命令来删除内容:plt.cla()清除当前图形中当前处于活动状态的轴。它使其他轴保持不变。plt.clf()清除整个当前图形。与所有的轴,但保持窗口打开,以便它可以在其他地块上重复使用。plt.close()关闭窗口,如果没有另外指定,它将是当前窗口。因此,哪种功能最适合您取决于您??的用例。close()函数还允许指定应关闭哪个窗口。参数可以是用figure(number_or_name)创建的窗口的编号或名称。也可以是获得的图形实例,即使用fig=figure()。如果没有给close()参数,当前活动的窗口将被关闭。此外,还有关闭所有数字的语法close('all')。总结一下经验,就是我们在使用matplotlib.pyplot的时候,后面需要加一个release操作。一般来说,这是经验不足造成的错误。最终的解决方案并不复杂,但是着重介绍了故障排除的过程和方法,收获颇丰。
