排除瓶颈和加速django项目
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
作者:?Desmond Chen
本篇中我們介紹一些基本的查找和加速django項(xiàng)目的策略.
1. 先等等
首先我們需要明白, 錯(cuò)誤的優(yōu)化不是什么好事. 如果你的項(xiàng)目只是小到中等規(guī)模, 并且加載速度過(guò)得去, 那么你完全沒(méi)有必要進(jìn)行優(yōu)化.
如果你項(xiàng)目的用戶(hù)在持續(xù)穩(wěn)定的增加, 并且達(dá)到了一定的數(shù)目, 那么請(qǐng)往下看.
2. 加速Q(mào)uery查詢(xún)
如果一個(gè)頁(yè)面中query數(shù)太多, 或一個(gè)query得到的數(shù)據(jù)太大, 都會(huì)導(dǎo)致加載速度變慢. 首先你可以看一下Django官網(wǎng)關(guān)于數(shù)據(jù)庫(kù)優(yōu)化的文檔:?https://docs.djangoproject.com/en/1.9/topics/db/optimization/.
a. 使用django-debug-toolbar
django-debug-toolbar可以找到query的來(lái)源, 并且找到:
- 重復(fù)的query
- 產(chǎn)生大量query的ORM語(yǔ)句
- 慢query
你對(duì)哪些頁(yè)面載入較慢應(yīng)該有個(gè)大致的了解, 所以你只需要使用django-debug-toolbar打開(kāi)這些頁(yè)面, 查看是哪些query拖慢了整體速度.
b. 減少query數(shù)
一旦找到了哪些頁(yè)面包含過(guò)多的query數(shù)后, 我們便可以采取措施減少query數(shù):
- 在ORM中使用select_related()減少query數(shù): 使用select_related()會(huì)自動(dòng)擴(kuò)展外鍵關(guān)系, 將外鍵中的數(shù)據(jù)提前合并到本次query. 如果使用CBV, django-braces的SelectRelatedMixin達(dá)到同樣的目地. 但要小心query擴(kuò)展的過(guò)深.
- 如果同樣的query發(fā)生多次, 那么將其移到view中, 在使用context將其傳到template中.
- 使用redis等caching, 然后測(cè)試.
- 使用django.utils.functional.cached_property修飾器, 將query結(jié)果cache在內(nèi)存中.
c. query提速
獲取一個(gè)大的query結(jié)果同樣也會(huì)影響速度, 因此我們首先需要:
- 確保index起到了加速query的作用
- 理解在部署服務(wù)器中index的作用, 分析理解數(shù)據(jù)庫(kù)中真正發(fā)生了什么
- 查看ORM生成的raw SQL語(yǔ)句
- 開(kāi)啟數(shù)據(jù)庫(kù)的 slow query logging功能, 并查看慢query發(fā)生的頻率
- 使用django-debug-toolbar找到慢query
然后我們便可以:
- 重寫(xiě)代碼, 使query獲得更小的片段
- 重寫(xiě)代碼, 使query更好的利用index
- 使用raw SQL語(yǔ)句代替ORM生成的慢SQL語(yǔ)句
d. ATOMIC_REQUESTS選項(xiàng)
大多數(shù)django項(xiàng)目在A(yíng)TOMIC_REQUESTS=True的狀況下運(yùn)行都沒(méi)有什么問(wèn)題. 如果你的瓶頸分析顯示數(shù)據(jù)庫(kù)transaction導(dǎo)致了延遲, 那么你可以選擇將ATOMIC_REQUESTS=False
3. 數(shù)據(jù)庫(kù)優(yōu)化
除了以上提到的query優(yōu)化外, 你可以更進(jìn)一步的進(jìn)行數(shù)據(jù)庫(kù)優(yōu)化, 相信這方面的書(shū)或文章已經(jīng)很多了, 我們不進(jìn)行深入討論了. 主要是以下幾點(diǎn):
a. 哪些不屬于數(shù)據(jù)庫(kù)
有兩種數(shù)據(jù)不應(yīng)該儲(chǔ)存在數(shù)據(jù)庫(kù)中, 一個(gè)是log信息, 另一個(gè)則是經(jīng)常變化的數(shù)據(jù). log信息在開(kāi)發(fā)時(shí)看似沒(méi)有什么影響, 但在正式服務(wù)器上運(yùn)行時(shí), 可能會(huì)拖慢數(shù)據(jù)庫(kù), 因此我們建議使用Splunk, Loggly這樣的第三方服務(wù)或使用NoSQL數(shù)據(jù)庫(kù)保存這些數(shù)據(jù). 經(jīng)常變換的數(shù)據(jù)比如django.contrib.sessions, django.contrib.messages等應(yīng)盡量保存到Memcached, Redis, Riak或其他NoSQL數(shù)據(jù)庫(kù)中.
b. PostgreSQL
對(duì)于postgres, 在正式服務(wù)器中一定要保證設(shè)置正確. 具體的設(shè)置方法可以自行g(shù)oogle之. 還可以參考書(shū) "Postgresql 9.0 high performance".
c. MySQL
MySQL容易安裝和運(yùn)行, 但如何優(yōu)化需要長(zhǎng)時(shí)間的經(jīng)驗(yàn)和理解. 我們推薦書(shū)"high performance MySQL".
4. 使用Memcached或Redis進(jìn)行Query Cache
你可以使用Django自帶的caching系統(tǒng)配合Memcached或Redis, 輕松的完成整站cache的配置. 也可以使用Django的Low-level API完成復(fù)雜的設(shè)置.
重要的是, 你需要確定哪些需要cache, 哪些不需要cache. 你需要考慮, 哪些view/template包含的query最多? 哪些URL被瀏覽的最多? 被cache的頁(yè)面何時(shí)需要失效處理?
我們也可以使用第三方package: 比如django-cache-machine, johnny-cache等.
5. 最小化HTML, CSS和JavaScript文件
當(dāng)瀏覽器呈現(xiàn)網(wǎng)頁(yè)時(shí), 必須載入HTML, CSS, JavaScript和圖片. 所有這些文件都會(huì)消耗用戶(hù)的帶寬, 使瀏覽速度下降. 雖然Django自帶了GZipMiddleware和{% spaceless %} template tag, 還有WSGI的 middleware都能幫助我們減小這些文件. 但使用以上方法都會(huì)增加Django自身的系統(tǒng)資源占有量, 可能會(huì)導(dǎo)致瓶頸. 最好的方式則是將這一操作交給Apache或Nginx這些web server, 比如利用PageSpeed Module.
當(dāng)然django的第三方package來(lái)壓縮和最小化CSS和JavaScript文件也是可行的, 常見(jiàn)的插件有django-pipeline, django-compressor, django-htmlmin等.
6. 使用Upstream caching或CDN
使用Varnish等upstream caching也能加快系統(tǒng)的載入速度. 當(dāng)然我們還可以AWS等云服務(wù)部署自己的CDN, 為全球的用戶(hù)提供快速的圖片, 視頻, CSS文件和JavaScript的載入.
?
原文鏈接: http://www.weiguda.com/blog/33/
轉(zhuǎn)載于:https://my.oschina.net/sukai/blog/873076
總結(jié)
以上是生活随笔為你收集整理的排除瓶颈和加速django项目的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 从杂技表演到日剧BGM(r12笔记第23
- 下一篇: Clojure Web 开发 -- Ri