一次django内存异常排查
起因
Django
作为 Python
著名的Web
框架,相信很多人都在用,自己工作中也有项目项目在用,而在最近几天的使用中发现,部署Django
程序的服务器出现了内存问题,现象就是运行一段时间之后,内存占用非常高,最终会把服务器的内存耗尽,对于Python
项目出现内存问题,自己之前处理过一次,所以并没有第一次解决时的慌张,自己之前把解决方法也整理了博客:https://www.cnblogs.com/zhaof/p/10031945.html
但是事情似乎并没有我想的那么简单,自己尝试用之前的的方法tracemalloc
库进行问题的排查,但是问题来了实际的项目中有快一百多个接口,怎么排查?难道一个一个接口进行测试排查,但是时间又比较紧急,可能又来不及了。对比上次自己解决是因为上次的项目比较简单,相对来说定位问题比较容易,那么这次怎么处理呢?
处理过程
一般Python
项目其实是很少出现内存问题的,一般都是自己代码写的有问题导致的,而对于这次出现的问题,自己的排查思路(对于web 接口类型的项目):
- 先排查调用比较频繁的接口
- 然后排查数据汇总接口(查询比较复杂)
- 如果上述还没有查出来,再排查剩余的接口
在这次的问题排查中,自己大致也是按照这个思路进行的,在对调用频繁的接口进行排查时,并没有发现内存的异常,而出现内存的问题则是在数据汇总的相关接口上。
其实这种接口对于初级开发可能是容易出问题的地方,首先这种接口查询的数据相对其他接口会比较复杂,如果编码基础又不是特别好,可能就会在这些接口上出现bug.
而在这次的排查中,最终确定是在一个汇总数据的接口上,定位到问题处在了Django ORM
使用不当导致的。自己通过一个简单代码实例来说明:
class Student(models.Model):
name = models.CharField(max_length=20)
name2 = models.CharField(max_length=20)
name3 = models.CharField(max_length=20)
name4 = models.CharField(max_length=20)
name5 = models.CharField(max_length=20)
name6 = models.CharField(max_length=20)
name7 = models.CharField(max_length=20)
name8 = models.CharField(max_length=20)
name9 = models.CharField(max_length=20)
name10 = models.CharField(max_length=20)
name11 = models.CharField(max_length=20)
name12 = models.CharField(max_length=20)
name13 = models.CharField(max_length=20)
name14 = models.CharField(max_length=20)
name15 = models.CharField(max_length=20)
age = models.IntegerField(default=0)
正常情况,我们的表字段会比较多,这里就通过多个name来模拟,出现题的代码就出在关于这个表的接口上:
def index(request):
studets = Student.objects.filter(age__gt=20)
if studets:
pass
return HttpResponse("test memory")
为了让内存问题容易复现,我通过脚本向Student中插入了20000条数据,当然这里数据越多,问题越明显
通过一个测试脚本并发请求这个接口,观察内存情况,你会发现,内存会出现瞬间上涨的情况,并且如果你的数据越多,请求越多,你的内存可能会在一段时间居高不下,并且逐渐上涨。问题出在哪里了?
其实很简单,问题出在了代码中的if 判断那里,我们通过filter 查询返回的是QuerySet 类型的数据,而我们过滤之后的数据可能会存在非常多的时候,这个时候我们通过if 直接判断,自己的理解这个地方会将整个QuerySet加载到内存中,从而出现内存占用过高的问题,而如果并且这个时候这个接口的响应速度也是非常会变慢,而这个QuerySet 中的数据越多,内存占用越明显。
在Django
的文档中其实做了说明
exists
()¶Returns
True
if theQuerySet
contains any results, andFalse
if not. This tries to perform the query in the simplest and fastest way possible, but it does execute nearly the same query as a normalQuerySet
query.
exists()
is useful for searches relating to both object membership in aQuerySet
and to the existence of any objects in aQuerySet
, particularly in the context of a largeQuerySet
.The most efficient method of finding whether a model with a unique field (e.g.
primary_key
) is a member of aQuerySet
is:entry = Entry.objects.get(pk=123)
if some_queryset.filter(pk=entry.pk).exists():
print("Entry contained in queryset")
Which will be faster than the following which requires evaluating and iterating through the entire queryset:
if entry in some_queryset:
print("Entry contained in QuerySet")
And to find whether a queryset contains any items:
if some_queryset.exists():
print("There is at least one object in some_queryset")
Which will be faster than:
if some_queryset:
print("There is at least one object in some_queryset")
… but not by a large degree (hence needing a large queryset for efficiency gains).
Additionally, if a
some_queryset
has not yet been evaluated, but you know that it will be at some point, then usingsome_queryset.exists()
will do more overall work (one query for the existence check plus an extra one to later retrieve the results) than usingbool(some_queryset)
, which retrieves the results and then checks if any were returned.
所以对于我们的代码我们只需要把if 判断地方改成if not studets.exists()
就可以解决问题。
这是一个很小的知识点,但是如果使用不对,可能就会造成非常严重的内存问题。
总结
- 除了单元测试,还需要做大数据量测试,这次的问题如果在测试的时候做过一定数据量的测试,可能很早就能及时发现问题
- 对于基础的库的使用要更加熟悉
- 排查问题的思路要明确,不然可能会无从下手
延伸阅读
- https://docs.djangoproject.com/en/3.0/ref/models/querysets/
- https://www.cnblogs.com/zhaof/p/10031945.html
一次django内存异常排查的更多相关文章
- 嵌入式开发之内核内存异常排查---关闭oom killer
通过执行以下命令,可以在1分钟内对系统资源使用情况有个大致的了解.uptimedmesg | tailvmstat 1mpstat -P ALL 1pidstat 1iostat -xz 1free ...
- 华为云数据库GaussDB(for Cassandra)揭秘第二期:内存异常增长的排查经历
摘要:华为云数据库GaussDB(for Cassandra) 是一款基于计算存储分离架构,兼容Cassandra生态的云原生NoSQL数据库:它依靠共享存储池实现了强一致,保证数据的安全可靠. 本文 ...
- Chrome JS内存泄漏排查方法(Chrome Profiles)
原文网址:http://blog.csdn.net/kaitiren/article/details/19974269 JS内存泄漏排查方法(Chrome Profiles) Google Ch ...
- Spring Boot引起的“堆外内存泄漏”排查及经验总结
小结: 检索词:C++内存分配器.jvm内存模型.gdb.内存泄露 https://tech.meituan.com/2019/01/03/spring-boot-native-memory-leak ...
- Netty堆外内存泄露排查与总结
导读 Netty 是一个异步事件驱动的网络通信层框架,用于快速开发高可用高性能的服务端网络框架与客户端程序,它极大地简化了 TCP 和 UDP 套接字服务器等网络编程. Netty 底层基于 JDK ...
- 【转载】Spring Boot引起的“堆外内存泄漏”排查及经验总结
背景 为了更好地实现对项目的管理,我们将组内一个项目迁移到MDP框架(基于Spring Boot),随后我们就发现系统会频繁报出Swap区域使用量过高的异常.笔者被叫去帮忙查看原因,发现配置了4G堆内 ...
- 内存泄漏排查之:Show me your Memory
java 语言有个神奇的地方,那就是你时不时会去关注下内存.(当然了,任何牛逼的同学都应该关注内存) 今天我们就来这么场景吧:某应用运行了一段时间后,ecs监控报警了,内存比较高了,怎么办?随着时间的 ...
- 深入理解JVM虚拟机11:Java内存异常原理与实践
本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutori ...
- Netty堆外内存泄漏排查,这一篇全讲清楚了
上篇文章介绍了Netty内存模型原理,由于Netty在使用不当会导致堆外内存泄漏,网上关于这方面的资料比较少,所以写下这篇文章,专门介绍排查Netty堆外内存相关的知识点,诊断工具,以及排查思路提供参 ...
随机推荐
- CentOS7开机报错piix4_smbus ****host smbus controller not enabled
vi /etc/modprobe.d/blacklist.conf 输入:blacklist i2c_piix4 保存退出::wq 重启:reboot (完)
- 一、web自动化快速使用
1.什么是Selenium? selenium是一款基于web网页的UI自动化测试的框架,用来做web自动化测试 支持多浏览器操作,ie.firefox.chrome.edge.safaria ...
- 移动端H5页面_input获取焦点时,虚拟键盘挡住input输入框解决方法
在移动端h5开发的时候,发现如果input在页面底部,当触发input焦点的时候会弹出系统虚拟键盘,虚拟键盘会遮挡input输入框.这会很影响用户体验,于是在网上找到了如下的解决办法: 方法一:使用w ...
- HDU 3911 Black and White (线段树,区间翻转)
[题目地址] vjudge HDU [题目大意] 海滩上有一堆石头. 石头的颜色是白色或黑色. 小肥羊拥有魔术刷,她可以改变连续石的颜色,从黑变白,从白变黑. 小肥羊非常喜欢黑色,因此她想知道范围 ...
- [网鼎杯 2020 青龙组]AreUSerialz
题目分析 <?php include("flag.php"); highlight_file(FILE); class FileHandler { protected $op ...
- ArrayList源码分析-jdk11 (18.9)
目录 1.概述 2.源码分析 2.1参数 2.2 构造方法 2.2.1 无参构造方法 2.2.2 构造空的具有特定初始容量值方法 2.2.3构造一个包含指定集合元素的列表,按照集合的迭代器返回它们的顺 ...
- java 面向对象(十六):Object类的使用
1.java.lang.Object类的说明: * 1.Object类是所Java类的根父类 * 2.如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object ...
- 数据可视化之分析篇(九)PowerBI数据分析实践第三弹 | 趋势分析法
https://zhuanlan.zhihu.com/p/133484654 以财务报表分析为例,介绍通用的分析方法论,整体架构如下图所示: (点击查看大图) 我会围绕这五种不同的方法论,逐步阐述他们 ...
- 数据可视化实例(十五):有序条形图(matplotlib,pandas)
偏差 (Deviation) 有序条形图 (Ordered Bar Chart) 有序条形图有效地传达了项目的排名顺序. 但是,在图表上方添加度量标准的值,用户可以从图表本身获取精确信息. https ...
- Python之函数、递归、内置函数
本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...