记一次Django响应超慢的解决过程


Posted in Python onSeptember 17, 2020

在本地windows机器开发的Django项目运行正常,放到服务器上后响应超慢,花了一整个工作日没找到原因(非常绝望),又花了一整个周末才找到原因和临时解决办法,如果你的项目超慢可以参考一下解决思路。

排查过程:

1.怀疑是Python环境问题,到服务器上各种虚拟环境版本进行尝试,无果。

2.因为用了mysql数据库,开始用pymysql包连接改动了一些参数,担心是驱动问题导致数据库查的慢,更换mysqlclient包后,响应依旧慢。 

3.担心是有什么报错导致慢,于是艰难地开启了debug模式(由于用了pymysql所以开启debug模式也会有个报错),开启之后Django反应慢但没有任何报错,绝望~

4.都说用uwsgi中间件部署Django能加快响应速度,尝试之,没用。

5.作为运维人员的思路来了-整个链路监控吧,看看哪个环节慢了。在网上找到了django性能监控工具django-silk,装上之后发现只能看到请求耗时、sql查询耗时,sql查询耗时就几ms,也不慢啊,哭死!

6.是不是模板渲染或者代码有问题导致慢呢?

views.py中新建一个方法,不做任何处理,直接返回一个字符串,依旧慢!

7.从客户端发出请求到views.py处理计算这个过程很慢?

views.py的处理函数中增加print('test'),在浏览器中刷新网页后,查看Django输出,请求后要15s才能看到打印test。 

8.客户端到服务器网络慢?

服务器上新建一个空白的Django项目,运行在相同的端口上,反应正常,网络没问题。 

9.从Django接受到请求到views.py进行逻辑处理中间这个过程很慢!中间经过了django中间件middleware的处理,中间件导致的慢?

依次注释掉能注释的中间件,然后刷请求看浏览器发出请求到Django输出test的延时。

发现注释掉一个自定义的中间件后,Django很快就能输出test(看到了希望)。但是正常业务处理方法响应依旧慢。 

10.自定义中间做了什么,怎么会耗费这么长时间?

查看中间件代码,发现每次请求进来Django进来以后,都要查询数据库,判断当前的url路径是否需要进行认证。

但这也是一次简单的数据库查询而已啊,为什么会这么慢,而且前面django-silk中也显示数据库查询响应很快?

有一点可以肯定的是Django查数据库这个动作耗费了大量的时间! 

11.既然查询数据库这个过程慢,那抓个到数据库的包看一下?

一顿操作后发现,当接收到请求后服务器会给数据库发一点数据,然后过了10多s后又发了一堆数据,等这一堆数据打传输完后浏览器上网页就返回了,这肯定跟响应慢有联系!深挖!

linux上抓包保存到文件,下载到windows上用wireshark分析发现:当Django收到用户请求后,会主动与数据库主机进行tcp连接,三次握手很快就成功了,然后等待了15s才收到MySQL的greet信息,才进行后续的sql查询。这说明服务器很快就与数据库主机建立了连接,但mysql应用等了15s才响应。此处不理解的,可以详细看一下MySQL协议。 

12.由于公司的DB是由DBA负责的,而且现在也是周末,所以暂时没办法继续深挖DB原因。接下来怎么办呢,怎么解决Django响应慢的问题?

在服务器上继续抓包,想对比一下主机上其他应用查询MySQL有什么差异,发现其他应用连接MySQL时一样会有5s的延时。在分析包的过程中发现别的应用会发送ping这样的请求,咦,这不是心跳包吗?别的应用是不是有会话保持啥的?所以没看出来响应慢?

13.给Django也设置一下数据库长连接会话保持试一下?

百度上关于这块的文章都比较老了,都是通过sqlalchemy的连接池管理可以保持数据库的长连接和复用,要改源码操作起来比较麻烦。而且都是Django 1.4时代的解决办法了,现在都Django2.2了,官方有没有提供长连接的机制支持呢?百度和查官方文档后发现配置数据库连接信息时有个可选参数叫“CONN_MAX_AGE”,默认情况下值为0,即数据库查询连接用完之后就释放掉了,新的查询又要重新建立一次连接。

将参数设置为2个小时,再次实验。启动Django后,第一次请求还是很慢,但后面的请求就加快了,问题得到了临时解决!

Todo: 至于数据库为什么要15s才响应连接,这个上班后再找DBA了解具体原因。

寄语:这次问题排查真的很艰难,尝试了各种办法,花了很多时间,终于通过抓包找到了相关的原因。讲真,通过这次问题的排查让我有增加了很多Django的知识!希望能对你有所帮助。

20200531更新:连接mysql慢的原因

为什么mysql响应这么慢,百度一番后发现原因

mysql建立连接之前会根据连接的ip反向查找对应的主机名,这一步会涉及DNS反向解析(如果本地hosts文件没有指定就会找其他服务器查询),这个过程会消耗时间。

于是登陆数据库所在主机,通过命令"nslookup IP地址"分别查询本地IP和服务器IP,本地IP查询结果很快返回(不在一个网段找不到),服务器IP结果非常慢直到超时否没返回,这就解释了为什么前文【windows机器反应快,linux反应慢】的问题。至于为什么反向解析服务器IP这么慢,这个问题就不再继续挖下去了,应该是网管没有配置好相关的解析吧。

解决办法:禁用反向解析,找到mysql的配置文件/etc/my.cnf,增加一行配置,重启以后数据库响应速度就完美了。

[mysqld]
skip-name-resolve

既然这个反向解析这么耗时,为什么还要有这个流程呢?

还记得mysql的授权命令吗:

grant all priviledges on *.* to "user"@"%" identified by "pass"

@后面的%就代表任意的主机名和ip地址,对!这个地方是可以根据主机名来授权的,如果把反向DNS解析关掉了,这里就会有问题,授权的时候就只能根据ip进行授权啦~

到此这篇关于记一次Django响应超慢的解决过程的文章就介绍到这了,更多相关Django响应超慢内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python 安装setuptools和pip工具操作方法(必看)
May 22 Python
Python读取MRI并显示为灰度图像实例代码
Jan 03 Python
详解python使用Nginx和uWSGI来运行Python应用
Jan 09 Python
用TensorFlow实现戴明回归算法的示例
May 02 Python
如何利用python制作时间戳转换工具详解
Sep 12 Python
Windows下Anaconda2安装NLTK教程
Sep 19 Python
Python文件循环写入行时防止覆盖的解决方法
Nov 09 Python
Python中判断子串存在的性能比较及分析总结
Jun 23 Python
利用PyQt中的QThread类实现多线程
Feb 18 Python
Django获取model中的字段名和字段的verbose_name方式
May 19 Python
Keras自动下载的数据集/模型存放位置介绍
Jun 19 Python
python3.4中清屏的处理方法
Jul 06 Python
Visual Studio Code搭建django项目的方法步骤
Sep 17 #Python
Windows下pycharm安装第三方库失败(通用解决方案)
Sep 17 #Python
PyCharm中关于安装第三方包的三个建议
Sep 17 #Python
Scrapy项目实战之爬取某社区用户详情
Sep 17 #Python
django跳转页面传参的实现
Sep 17 #Python
解决Ubuntu18中的pycharm不能调用tensorflow-gpu的问题
Sep 17 #Python
Django mysqlclient安装和使用详解
Sep 17 #Python
You might like
phpmyadmin中配置文件现在需要绝密的短语密码的解决方法
2007/02/11 PHP
解析php开发中的中文编码问题
2013/08/08 PHP
php获取发送给用户的header信息的方法
2015/03/16 PHP
作为程序员必知的16个最佳PHP库
2015/12/09 PHP
Yii框架实现图片上传的方法详解
2017/05/20 PHP
laravel 自定义常量的两种方案
2019/10/14 PHP
PHP8.0新功能之Match表达式的使用
2020/07/19 PHP
Javascript 判断函数类型完美解决方案
2009/09/02 Javascript
JavaScript自定义等待wait函数实例分析
2015/03/23 Javascript
最新最热最实用的15个jQuery插件汇总
2015/07/05 Javascript
javascript生成不重复的随机数
2015/07/17 Javascript
javascript弹出拖动窗口
2015/08/11 Javascript
jQuery实现宽屏图片轮播实例教程
2015/11/24 Javascript
js弹出框、对话框、提示框、弹窗实现方法总结(推荐)
2016/05/31 Javascript
整理关于Bootstrap警示框的慕课笔记
2017/03/29 Javascript
微信小程序实战之顶部导航栏(选项卡)(1)
2020/06/19 Javascript
underscore之function_动力节点Java学院整理
2017/07/11 Javascript
深入探究angular2 UI组件之primeNG用法
2017/07/26 Javascript
微信小程序实现tab左右切换效果
2020/11/15 Javascript
Vue入门学习笔记【基本概念、对象、过滤器、指令等】
2019/04/13 Javascript
layui动态渲染生成左侧3级菜单的方法(根据后台返回数据)
2019/09/23 Javascript
基于vue+element实现全局loading过程详解
2020/07/10 Javascript
在vue中使用cookie记住用户上次选择的实例(本次例子中为下拉框)
2020/09/11 Javascript
[01:16:28]DOTA2-DPC中国联赛 正赛 iG vs Magma BO3 第二场 2月23日
2021/03/11 DOTA
Python  unittest单元测试框架的使用
2018/09/08 Python
用Python抢火车票的简单小程序实现解析
2019/08/14 Python
Python pip 常用命令汇总
2020/10/19 Python
Python+Appium实现自动化清理微信僵尸好友的方法
2021/02/04 Python
CSS3 选择器 属性选择器介绍
2012/01/21 HTML / CSS
HTML5的革新 结构之美
2011/06/20 HTML / CSS
Kiehl’s科颜氏西班牙官方网站:源自美国的植物护肤品牌
2020/02/22 全球购物
委托书范文
2014/04/02 职场文书
门店业绩提升方案
2014/06/08 职场文书
商务邀请函
2015/01/30 职场文书
销售会议开幕词
2016/03/04 职场文书
MySQL中TIMESTAMP类型返回日期时间数据中带有T的解决
2022/12/24 MySQL