掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
Instagram 目前部署了世界上最大規(guī)模的 Django Web 框架(該框架完全使用 Python 編寫)。我們最初選用 Python 是因?yàn)樗秘?fù)盛名的簡潔性與實(shí)用性,這非常符合我們的哲學(xué)思想——“先做簡單的事情”。但簡潔性也會帶來效率方面的折衷。Instagram 的規(guī)模在過去兩年中已經(jīng)翻番,并且最近已突破 5 億用戶,所以急需最大程度地提升 web 服務(wù)效率以便我們的平臺能夠繼續(xù)順利地擴(kuò)大。在過去的一年,我們已經(jīng)將效率計劃efficiency program提上日程,并在過去的六個月,我們已經(jīng)能夠做到無需向我們的 Django 層Django tiers添加新的容量來維持我們的用戶增長。我們將在本文分享一些由我們構(gòu)建的工具以及如何使用它們來優(yōu)化我們的日常部署流程。

“專業(yè)、務(wù)實(shí)、高效、創(chuàng)新、把客戶的事當(dāng)成自己的事”是我們每一個人一直以來堅持追求的企業(yè)文化。 成都創(chuàng)新互聯(lián)是您可以信賴的網(wǎng)站建設(shè)服務(wù)商、專業(yè)的互聯(lián)網(wǎng)服務(wù)提供商! 專注于網(wǎng)站制作、成都網(wǎng)站制作、軟件開發(fā)、設(shè)計服務(wù)業(yè)務(wù)。我們始終堅持以客戶需求為導(dǎo)向,結(jié)合用戶體驗(yàn)與視覺傳達(dá),提供有針對性的項目解決方案,提供專業(yè)性的建議,創(chuàng)新互聯(lián)建站將不斷地超越自我,追逐市場,引領(lǐng)市場!
為何需要提升效率?
Instagram,正如所有的軟件,受限于像服務(wù)器和數(shù)據(jù)中心能源這樣的物理限制。鑒于這些限制,在我們的效率計劃中有兩個我們希望實(shí)現(xiàn)的主要目標(biāo):
想要實(shí)現(xiàn)這些目標(biāo),我們意識到我們需要持續(xù)不斷地監(jiān)控我們的系統(tǒng)并與回歸regressions進(jìn)行戰(zhàn)斗。
定義效率
Web services 的瓶頸通常在于每臺服務(wù)器上可用的 CPU 時間。在這種環(huán)境下,效率就意味著利用相同的 CPU 資源完成更多的任務(wù),也就是說,每秒處理更多的用戶請求requests per second,RPS。當(dāng)我們尋找優(yōu)化方法時,我們面臨的第一個最大的挑戰(zhàn)就是嘗試量化我們當(dāng)前的效率。到目前為止,我們一直在使用“每次請求的平均 CPU 時間”來評估效率,但使用這種指標(biāo)也有其固有限制:
相對于 CPU 時間來說,CPU 指令是一種更好的指標(biāo),因?yàn)閷τ谙嗤恼埱螅鼤蟾嫦嗤臄?shù)字,不管 CPU 型號和 CPU 負(fù)載情況如何。我們選擇使用了一種叫做”每個活動用戶per active user“的指標(biāo),而不是將我們所有的數(shù)據(jù)關(guān)聯(lián)到每個用戶請求上。我們最終采用“每個活動用戶在高峰期間的 CPU 指令CPU instruction per active user during peak minute”來測量效率。我們建立好新的度量標(biāo)準(zhǔn)后,下一步就是通過對 Django 的分析來更多的了解一下我們的回歸。
Django web services 分析
通過分析我們的 Django web services,我們希望回答兩個主要問題:
想要回答第一個問題,我們需要追蹤“每個活動用戶的 CPU 指令CPU-instruction-per-active-user”指標(biāo)。如果該指標(biāo)增加,我們就知道已經(jīng)發(fā)生了一次 CPU 回歸。
我們?yōu)榇藰?gòu)建的工具叫做 Dynostats。Dynostats 利用 Django 中間件以一定的速率采樣用戶請求,記錄關(guān)鍵的效率以及性能指標(biāo),例如 CPU 總指令數(shù)、端到端請求時延、花費(fèi)在訪問內(nèi)存緩存(memcache)和數(shù)據(jù)庫服務(wù)的時間等。另一方面,每個請求都有很多可用于聚合的元數(shù)據(jù)metadata,例如端點(diǎn)名稱、HTTP 請求返回碼、服務(wù)該請求的服務(wù)器名稱以及請求中最新提交的哈希值hash。對于單個請求記錄來說,有兩個方面非常強(qiáng)大,因?yàn)槲覀兛梢栽诓煌木S度上進(jìn)行切割,那將幫助我們減少任何導(dǎo)致 CPU 回歸的原因。例如,我們可以根據(jù)它們的端點(diǎn)名稱聚合所有請求,正如下面的時間序列圖所示,從圖中可以清晰地看出在特定端點(diǎn)上是否發(fā)生了回歸。
CPU 指令對測量效率很重要——當(dāng)然,它們也很難獲得。Python 并沒有支持直接訪問 CPU 硬件計數(shù)器(CPU 硬件計數(shù)器是指可編程 CPU 寄存器,用于測量性能指標(biāo),例如 CPU 指令)的公共庫。另一方面,Linux 內(nèi)核提供了 perf_event_open 系統(tǒng)調(diào)用。通過 Python ctypes 橋接技術(shù)能夠讓我們調(diào)用標(biāo)準(zhǔn) C 庫的系統(tǒng)調(diào)用函數(shù)syscall,它也為我們提供了兼容 C 的數(shù)據(jù)類型,從而可以編程硬件計數(shù)器并從它們讀取數(shù)據(jù)。
使用 Dynostats,我們已經(jīng)可以找出 CPU 回歸,并探究 CPU 回歸發(fā)生的原因,例如哪個端點(diǎn)受到的影響最多,誰提交了真正會導(dǎo)致 CPU 回歸的變更等。然而,當(dāng)開發(fā)者收到他們的變更已經(jīng)導(dǎo)致一次 CPU 回歸發(fā)生的通知時,他們通常難以找出問題所在。如果問題很明顯,那么回歸可能就不會一開始就被提交!
這就是為何我們需要一個 Python 分析器,(一旦 Dynostats 發(fā)現(xiàn)了它)從而使開發(fā)者能夠使用它找出回歸發(fā)生的根本原因。不同于白手起家,我們決定對一個現(xiàn)成的 Python 分析器 cProfile 做適當(dāng)?shù)男薷?。cProfile 模塊通常會提供一個統(tǒng)計集合來描述程序不同的部分執(zhí)行時間和執(zhí)行頻率。我們將 cProfile 的定時器timer替換成了一個從硬件計數(shù)器讀取的 CPU 指令計數(shù)器,以此取代對時間的測量。我們在采樣請求后產(chǎn)生數(shù)據(jù)并把數(shù)據(jù)發(fā)送到數(shù)據(jù)流水線。我們也會發(fā)送一些我們在 Dynostats 所擁有的類似元數(shù)據(jù),例如服務(wù)器名稱、集群、區(qū)域、端點(diǎn)名稱等。
在數(shù)據(jù)流水線的另一邊,我們創(chuàng)建了一個消費(fèi)數(shù)據(jù)的尾隨者tailer。尾隨者的主要功能是解析 cProfile 的統(tǒng)計數(shù)據(jù)并創(chuàng)建能夠表示 Python 函數(shù)級別的 CPU 指令的實(shí)體。如此,我們能夠通過 Python 函數(shù)來聚合 CPU 指令,從而更加方便地找出是什么函數(shù)導(dǎo)致了 CPU 回歸。
監(jiān)控與警報機(jī)制
在 Instagram,我們每天部署 30-50 次后端服務(wù)。這些部署中的任何一個都能發(fā)生 CPU 回歸的問題。因?yàn)槊看伟l(fā)生通常都包含至少一個差異diff,所以找出任何回歸是很容易的。我們的效率監(jiān)控機(jī)制包括在每次發(fā)布前后都會在 Dynostats 中掃描 CPU 指令,并且當(dāng)變更超出某個閾值時發(fā)出警告。對于長期會發(fā)生 CPU 回歸的情況,我們也有一個探測器為負(fù)載最繁重的端點(diǎn)提供日常和每周的變更掃描。
部署新的變更并非觸發(fā)一次 CPU 回歸的唯一情況。在許多情況下,新的功能和新的代碼路徑都由全局環(huán)境變量global environment variables,GEV控制。 在一個計劃好的時間表上,給一部分用戶發(fā)布新功能是很常見事情。我們在 Dynostats 和 cProfile 統(tǒng)計數(shù)據(jù)中為每個請求添加了這個信息作為額外的元數(shù)據(jù)字段。按這些字段將請求分組可以找出由全局環(huán)境變量(GEV)改變導(dǎo)致的可能的 CPU 回歸問題。這讓我們能夠在它們對性能造成影響前就捕獲到 CPU 回歸。
接下來是什么?
Dynostats 和我們定制的 cProfile,以及我們建立的支持它們的監(jiān)控和警報機(jī)制能夠有效地找出大多數(shù)導(dǎo)致 CPU 回歸的元兇。這些進(jìn)展已經(jīng)幫助我們恢復(fù)了超過 50% 的不必要的 CPU 回歸,否則我們就根本不會知道。
我們?nèi)匀贿€有一些可以提升的方面,并很容易將它們地加入到 Instagram 的日常部署流程中:
鑒于我們在為 Instagram 的 web service 構(gòu)建效率框架中所投入的工作,所以我們對于將來使用 Python 繼續(xù)擴(kuò)展我們的服務(wù)很有信心。我們也開始向 Python 語言本身投入更多,并且開始探索從 Python 2 轉(zhuǎn)移 Python 3 之道。我們將會繼續(xù)探索并做更多的實(shí)驗(yàn)以繼續(xù)提升基礎(chǔ)設(shè)施與開發(fā)者效率,我們期待著很快能夠分享更多的經(jīng)驗(yàn)。
本文作者 Min Ni 是 Instagram 的軟件工程師。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流