最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

記一次django內(nèi)存異常排查及解決方法

 更新時(shí)間:2020年08月07日 09:10:51   作者:syncd  
這篇文章主要給大家介紹了關(guān)于一次django內(nèi)存異常排查記解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用django具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

起因

Django 作為 Python著名的Web框架,相信很多人都在用,自己工作中也有項(xiàng)目項(xiàng)目在用,而在最近幾天的使用中發(fā)現(xiàn),部署Django程序的服務(wù)器出現(xiàn)了內(nèi)存問(wèn)題,現(xiàn)象就是運(yùn)行一段時(shí)間之后,內(nèi)存占用非常高,最終會(huì)把服務(wù)器的內(nèi)存耗盡,對(duì)于Python項(xiàng)目出現(xiàn)內(nèi)存問(wèn)題,自己之前處理過(guò)一次,所以并沒(méi)有第一次解決時(shí)的慌張,自己之前把解決方法也整理了:http://m.fzitv.net/article/151604.htm

但是事情似乎并沒(méi)有我想的那么簡(jiǎn)單,自己嘗試用之前的的方法tracemalloc庫(kù)進(jìn)行問(wèn)題的排查,但是問(wèn)題來(lái)了實(shí)際的項(xiàng)目中有快一百多個(gè)接口,怎么排查?難道一個(gè)一個(gè)接口進(jìn)行測(cè)試排查,但是時(shí)間又比較緊急,可能又來(lái)不及了。對(duì)比上次自己解決是因?yàn)樯洗蔚捻?xiàng)目比較簡(jiǎn)單,相對(duì)來(lái)說(shuō)定位問(wèn)題比較容易,那么這次怎么處理呢?

處理過(guò)程

一般Python項(xiàng)目其實(shí)是很少出現(xiàn)內(nèi)存問(wèn)題的,一般都是自己代碼寫(xiě)的有問(wèn)題導(dǎo)致的,而對(duì)于這次出現(xiàn)的問(wèn)題,自己的排查思路(對(duì)于web 接口類型的項(xiàng)目):

  1. 先排查調(diào)用比較頻繁的接口
  2. 然后排查數(shù)據(jù)匯總接口(查詢比較復(fù)雜)
  3. 如果上述還沒(méi)有查出來(lái),再排查剩余的接口

在這次的問(wèn)題排查中,自己大致也是按照這個(gè)思路進(jìn)行的,在對(duì)調(diào)用頻繁的接口進(jìn)行排查時(shí),并沒(méi)有發(fā)現(xiàn)內(nèi)存的異常,而出現(xiàn)內(nèi)存的問(wèn)題則是在數(shù)據(jù)匯總的相關(guān)接口上。

其實(shí)這種接口對(duì)于初級(jí)開(kāi)發(fā)可能是容易出問(wèn)題的地方,首先這種接口查詢的數(shù)據(jù)相對(duì)其他接口會(huì)比較復(fù)雜,如果編碼基礎(chǔ)又不是特別好,可能就會(huì)在這些接口上出現(xiàn)bug.

而在這次的排查中,最終確定是在一個(gè)匯總數(shù)據(jù)的接口上,定位到問(wèn)題處在了Django ORM 使用不當(dāng)導(dǎo)致的。自己通過(guò)一個(gè)簡(jiǎn)單代碼實(shí)例來(lái)說(shuō)明:

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)

正常情況,我們的表字段會(huì)比較多,這里就通過(guò)多個(gè)name來(lái)模擬,出現(xiàn)題的代碼就出在關(guān)于這個(gè)表的接口上:

def index(request):
 studets = Student.objects.filter(age__gt=20)
 if studets:
  pass
 return HttpResponse("test memory")

為了讓內(nèi)存問(wèn)題容易復(fù)現(xiàn),我通過(guò)腳本向Student中插入了20000條數(shù)據(jù),當(dāng)然這里數(shù)據(jù)越多,問(wèn)題越明顯

通過(guò)一個(gè)測(cè)試腳本并發(fā)請(qǐng)求這個(gè)接口,觀察內(nèi)存情況,你會(huì)發(fā)現(xiàn),內(nèi)存會(huì)出現(xiàn)瞬間上漲的情況,并且如果你的數(shù)據(jù)越多,請(qǐng)求越多,你的內(nèi)存可能會(huì)在一段時(shí)間居高不下,并且逐漸上漲。問(wèn)題出在哪里了?

其實(shí)很簡(jiǎn)單,問(wèn)題出在了代碼中的if 判斷那里,我們通過(guò)filter 查詢返回的是QuerySet 類型的數(shù)據(jù),而我們過(guò)濾之后的數(shù)據(jù)可能會(huì)存在非常多的時(shí)候,這個(gè)時(shí)候我們通過(guò)if 直接判斷,自己的理解這個(gè)地方會(huì)將整個(gè)QuerySet加載到內(nèi)存中,從而出現(xiàn)內(nèi)存占用過(guò)高的問(wèn)題,而如果并且這個(gè)時(shí)候這個(gè)接口的響應(yīng)速度也是非常會(huì)變慢,而這個(gè)QuerySet 中的數(shù)據(jù)越多,內(nèi)存占用越明顯。

在Django的文檔中其實(shí)做了說(shuō)明

exists()¶
Returns True if the QuerySet contains any results, and False 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 normal QuerySet query.

exists() is useful for searches relating to both object membership in a QuerySet and to the existence of any objects in a QuerySet, particularly in the context of a large QuerySet.

The most efficient method of finding whether a model with a unique field (e.g. primary_key) is a member of a QuerySet 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 using some_queryset.exists() will do more overall work (one query for the existence check plus an extra one to later retrieve the results) than using bool(some_queryset), which retrieves the results and then checks if any were returned.

所以對(duì)于我們的代碼我們只需要把if 判斷地方改成if not studets.exists() 就可以解決問(wèn)題。

這是一個(gè)很小的知識(shí)點(diǎn),但是如果使用不對(duì),可能就會(huì)造成非常嚴(yán)重的內(nèi)存問(wèn)題。

總結(jié)

除了單元測(cè)試,還需要做大數(shù)據(jù)量測(cè)試,這次的問(wèn)題如果在測(cè)試的時(shí)候做過(guò)一定數(shù)據(jù)量的測(cè)試,可能很早就能及時(shí)發(fā)現(xiàn)

問(wèn)題

對(duì)于基礎(chǔ)的庫(kù)的使用要更加熟悉

排查問(wèn)題的思路要明確,不然可能會(huì)無(wú)從下手

延伸閱讀

到此這篇關(guān)于django內(nèi)存異常排查及解決方法的文章就介紹到這了,更多相關(guān)django內(nèi)存異常排查內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python發(fā)送郵件封裝實(shí)現(xiàn)過(guò)程詳解

    Python發(fā)送郵件封裝實(shí)現(xiàn)過(guò)程詳解

    這篇文章主要介紹了Python發(fā)送郵件封裝實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 用python做游戲的細(xì)節(jié)詳解

    用python做游戲的細(xì)節(jié)詳解

    在本篇內(nèi)容里小編給大家分享的是關(guān)于python做游戲的細(xì)節(jié)相關(guān)知識(shí)點(diǎn)內(nèi)容,有需要的朋友們跟著學(xué)習(xí)下。
    2019-06-06
  • Python json格式化打印實(shí)現(xiàn)過(guò)程解析

    Python json格式化打印實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了Python json格式化打印實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Python機(jī)器學(xué)習(xí)庫(kù)之Scikit-learn基本用法詳解

    Python機(jī)器學(xué)習(xí)庫(kù)之Scikit-learn基本用法詳解

    Scikit-learn?是?Python?中最著名的機(jī)器學(xué)習(xí)庫(kù)之一,它提供了大量實(shí)用的機(jī)器學(xué)習(xí)算法以及相關(guān)的工具,可以方便我們進(jìn)行數(shù)據(jù)挖掘和數(shù)據(jù)分析,在這篇文章中,我們將介紹?Scikit-learn?的基本使用,包括如何導(dǎo)入數(shù)據(jù)、預(yù)處理數(shù)據(jù)、選擇和訓(xùn)練模型,以及評(píng)估模型的性能
    2023-07-07
  • python如何構(gòu)建mock接口服務(wù)

    python如何構(gòu)建mock接口服務(wù)

    這篇文章主要介紹了python如何構(gòu)建mock接口服務(wù),幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2021-01-01
  • Python 切片索引越界的問(wèn)題(數(shù)組下標(biāo)越界)

    Python 切片索引越界的問(wèn)題(數(shù)組下標(biāo)越界)

    Python語(yǔ)言處理字符串、數(shù)組類的問(wèn)題時(shí)有一定概率需要使用切片方法,本文主要介紹了Python 切片索引越界的問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Python批量圖片去水印的方法

    Python批量圖片去水印的方法

    ​平常工作中,有時(shí)為了采用網(wǎng)絡(luò)的一些素材,但這些素材往往被打了水印,如果我們不懂PS就無(wú)法去掉水印,或者無(wú)法批量去掉水印。本文就介紹了Python批量圖片去水印的方法,感興趣的可以了解一下
    2021-05-05
  • python3.x+pyqt5實(shí)現(xiàn)主窗口狀態(tài)欄里(嵌入)顯示進(jìn)度條功能

    python3.x+pyqt5實(shí)現(xiàn)主窗口狀態(tài)欄里(嵌入)顯示進(jìn)度條功能

    這篇文章主要介紹了python3.x+pyqt5實(shí)現(xiàn)主窗口狀態(tài)欄里(嵌入)顯示進(jìn)度條功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 分析Python字符串拼接+=和join()哪個(gè)速度更快

    分析Python字符串拼接+=和join()哪個(gè)速度更快

    這篇文章主要分析了Python中字符串拼接+=和join()哪個(gè)速度更快,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Python實(shí)現(xiàn)數(shù)據(jù)濾波的示例詳解

    Python實(shí)現(xiàn)數(shù)據(jù)濾波的示例詳解

    這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)數(shù)據(jù)濾波的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03

最新評(píng)論

勃利县| 柳江县| 华安县| 延寿县| 定安县| 延庆县| 娄烦县| 邮箱| 广丰县| 浠水县| 安多县| 通渭县| 神农架林区| 襄汾县| 广元市| 东至县| 毕节市| 永平县| 宽城| 三都| 垦利县| 旌德县| 郯城县| 朔州市| 化德县| 临洮县| 镇江市| 正宁县| 上高县| 定结县| 内江市| 辽源市| 沁水县| 中卫市| 乌拉特中旗| 航空| 铜鼓县| 铜梁县| 广水市| 汕尾市| 渝北区|