记一次Django响应超慢的解决过程
作者:小伍子 发布时间:2021-11-23 13:35:57
在本地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进行授权啦~
来源:https://www.cnblogs.com/wurijie/p/12950633.html


猜你喜欢
- 一、前提概要效果:实现一个自定义tabBar,使消息tabBar能够显示消息数量,并通过全局共享的方式,控制消息数量需要的知识点如下:mob
- tkinter库:Python的标准Tk GUI工具包的接口示例:from tkinter import *root = Tk()#你的ui
- 定时任务是老生常谈了,因为我们总是需要定时修改特定的数据。实现它的方法肯定不止一种,但我在相当长一段时间里都是用程序编码去做的,今天突然想到
- 一、前言这几天宅在家里网上冲浪,无意间看到了一个比较有趣的项目,就是使用 Python 语言实现对视频中的人物的眨眼进行计数并描绘在图表中。
- 这篇文章主要介绍了Python爬虫爬取煎蛋网图片代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的
- 国产框架thinkPHP,是一款MVC框架,这个框架最初模拟JAVA的struts框架,使用单一入口文件模拟JAVA的过滤器,使用actio
- javascript Date.getUTCDay()方法按照通用时间在指定日期返回星期几。通过getUTCDay返回的值是对应
- 除了IE浏览器,其他所有主流的浏览器均支持原生的 Base64 编码:btoa(text) – base64 encodes text. a
- 具体代码如下所示:import tkinter as tkimport tkinter.messageboximport copyimpor
- 目录1. 前言2. 准备3. 实战1、获取目标应用的包名及初始化 Activity2、获取所有在线的设备3、群控打开目标应用4、封装执行步骤
- 这篇文章主要是想说,“引用只能指向具体对象而不能指向引用”//创建变量testArray 并引用数组 ["1&
- python刷CSDN访问量import requestsimport reimport timepayload = ""
- Pillow图像降噪处理由于成像设备、传输媒介等因素的影响,图像总会或多或少的存在一些不必要的干扰信息,我们将这些干扰信息统称为&l
- 前言数据处理过程中,经常会遇到数据有缺失值的情况,本文介绍如何用Pandas处理数据中的缺失值。一、什么是缺失值对数据而言,缺失值分为两种,
- PHP5.4才支持JSON_UNESCAPED_UNICODE这个参数,此参数是让中文字符在json_encode的时候不用转义,减少数据传
- 最近有网友在留言板里问到jRaiser和jQuery的冲突问题,特此写一篇文章进行解释。冲突的根源众所周知,jQuery是通过一个全局变量$
- 本文实例讲述了Python基于正则表达式实现检查文件内容的方法分享给大家供大家参考,具体如下:这个是之前就在学python,欣赏python
- 很多人认为python中的字典是无序的,因为它是按照hash来存储的,但是python中有个模块collections(英文,收集、集合),
- --创建链接服务器 exec sp_addlinkedserver &
- 利用Python,将多个excel文件合并为一个文件思路利用python xlrd包读取excle文件,然后将文件内容存入一个列表中,再利用