提公升服務效率就這麼簡單

2021-12-30 01:08:05 字數 3714 閱讀 7723

instagram 目前部署了世界上最大規模的 django web 框架(該框架完全使用 python 編寫)。我們最初選用 python 是因為它久負盛名的簡潔性與實用性,這非常符合我們的哲學思想——「先做簡單的事情」。但簡潔性也會帶來效率方面的折衷。

instagram 的規模在過去兩年中已經翻番,並且最近已突破 5 億使用者,所以急需最大程度地提公升 web 服務效率以便我們的平台能夠繼續順利地擴大。在過去的一年,我們已經將效率計畫提上日程,並在過去的六個月,我們已經能夠做到無需向我們的django 層新增新的容量來維持我們的使用者增長。我們將在本文分享一些由我們構建的工具以及如何使用它們來優化我們的日常部署流程。

為何需要提公升效率?

instagram,正如所有的軟體,受限於像伺服器和資料中心能源這樣的物理限制。鑑於這些限制,在我們的效率計畫中有兩個我們希望實現的主要目標:

instagram 應當能夠利用持續**發布正常地提供通訊服務,防止因為自然災害、區域性網路問題等造成某乙個資料中心區丟失。

instagram 應當能夠自由地滾動發布新產品和新功能,不必因容量而受阻。

想要實現這些目標,我們意識到我們需要持續不斷地監控我們的系統並與回歸進行戰鬥。

定義效率

web services 的瓶頸通常在於每台伺服器上可用的 cpu 時間。在這種環境下,效率就意味著利用相同的 cpu 資源完成更多的任務,也就是說,每秒處理更多的使用者請求。當我們尋找優化方法時,我們面臨的第乙個最大的挑戰就是嘗試量化我們當前的效率。到目前為止,我們一直在使用「每次請求的平均 cpu 時間」來評估效率,但使用這種指標也有其固有限制:

裝置多樣性。使用 cpu 時間來測量 cpu 資源並非理想方案,因為它同時受到 cpu 型號與 cpu 負載的影響。

請求影響資料。測量每次請求的 cpu 資源並非理想方案,因為在使用每次請求測量方案時,新增或移除輕量級或重量級的請求也會影響到效率指標。

相對於 cpu 時間來說,cpu 指令是一種更好的指標,因為對於相同的請求,它會報告相同的數字,不管 cpu 型號和 cpu 負載情況如何。我們選擇使用了一種叫做」每個活動使用者「的指標,而不是將我們所有的資料關聯到每個使用者請求上。我們最終採用「每個活動使用者在高峰期間的 cpu 指令」來測量效率。我們建立好新的度量標準後,下一步就是通過對 django 的分析來更多的了解一下我們的回歸。

django web services 分析

通過分析我們的 django web services,我們希望回答兩個主要問題:

cpu 回歸會發生嗎?

是什麼導致了 cpu 回歸發生以及我們該怎樣修復它?

想要回答第乙個問題,我們需要追蹤「每個活動使用者的 cpu 指令」指標。如果該指標增加,我們就知道已經發生了一次 cpu 回歸。

我們為此構建的工具叫做 dynostats。dynostats 利用 django 中介軟體以一定的速率取樣使用者請求,記錄關鍵的效率以及效能指標,例如 cpu 總指令數、端到端請求時延、花費在訪問記憶體快取(memcache)和資料庫服務的時間等。另一方面,每個請求都有很多可用於聚合的元資料,例如端點名稱、http 請求返回碼、服務該請求的伺服器名稱以及請求中最新提交的雜湊值。對於單個請求記錄來說,有兩個方面非常強大,因為我們可以在不同的維度上進行切割,那將幫助我們減少任何導致 cpu 回歸的原因。例如,我們可以根據它們的端點名稱聚合所有請求,正如下面的時間序列圖所示,從圖中可以清晰地看出在特定端點上是否發生了回歸。

cpu 指令對測量效率很重要——當然,它們也很難獲得。python 並沒有支援直接訪問 cpu 硬體計數器(cpu 硬體計數器是指可程式設計 cpu 暫存器,用於測量效能指標,例如 cpu 指令)的公共庫。另一方面,linux 核心提供了perf_event_open 系統呼叫。通過 python ctypes 橋接技術能夠讓我們呼叫標準 c 庫的系統呼叫函式 syscall,它也為我們提供了相容 c 的資料型別,從而可以程式設計硬體計數器並從它們讀取資料。

使用 dynostats,我們已經可以找出 cpu 回歸,並** cpu 回歸發生的原因,例如哪個端點受到的影響最多,誰提交了真正會導致 cpu 回歸的變更等。然而,當開發者收到他們的變更已經導致一次 cpu 回歸發生的通知時,他們通常難以找出問題所在。如果問題很明顯,那麼回歸可能就不會一開始就被提交!

這就是為何我們需要乙個 python 分析器,(一旦 dynostats 發現了它)從而使開發者能夠使用它找出回歸發生的根本原因。不同於白手起家,我們決定對乙個現成的 python 分析器 cprofile 做適當的修改。cprofile 模組通常會提供乙個統計集合來描述程式不同的部分執行時間和執行頻率。我們將 cprofile 的定時器替換成了乙個從硬體計數器讀取的 cpu 指令計數器,以此取代對時間的測量。我們在取樣請求後產生資料並把資料傳送到資料流水線。我們也會傳送一些我們在 dynostats 所擁有的類似元資料,例如伺服器名稱、集群、區域、端點名稱等。

在資料流水線的另一邊,我們建立了乙個消費資料的尾隨者。尾隨者的主要功能是解析 cprofile 的統計資料並建立能夠表示 python 函式級別的 cpu 指令的實體。如此,我們能夠通過 python 函式來聚合 cpu 指令,從而更加方便地找出是什麼函式導致了 cpu 回歸。

監控與警報機制

在 instagram,我們每天部署 30-50 次後端服務。這些部署中的任何乙個都能發生 cpu 回歸的問題。因為每次發生通常都包含至少乙個差異,所以找出任何回歸是很容易的。我們的效率監控機制包括在每次發布前後都會在 dynostats 中掃瞄 cpu 指令,並且當變更超出某個閾值時發出警告。對於長期會發生 cpu 回歸的情況,我們也有乙個探測器為負載最繁重的端點提供日常和每週的變更掃瞄。

部署新的變更並非觸發一次 cpu 回歸的唯一情況。在許多情況下,新的功能和新的**路徑都由全域性環境變數控制。 在乙個計畫好的時間表上,給一部分使用者發布新功能是很常見事情。我們在 dynostats 和 cprofile 統計資料中為每個請求新增了這個資訊作為額外的元資料字段。按這些欄位將請求分組可以找出由全域性環境變數(gev)改變導致的可能的 cpu 回歸問題。這讓我們能夠在它們對效能造成影響前就捕獲到 cpu 回歸。

接下來是什麼?

dynostats 和我們定製的 cprofile,以及我們建立的支援它們的監控和警報機制能夠有效地找出大多數導致 cpu 回歸的元凶。這些進展已經幫助我們恢復了超過 50% 的不必要的 cpu 回歸,否則我們就根本不會知道。

我們仍然還有一些可以提公升的方面,並很容易將它們地加入到 instagram 的日常部署流程中:

cpu 指令指標應該要比其它指標如 cpu 時間更加穩定,但我們仍然觀察了讓我們頭疼的差異。保持「訊雜比」合理地低是非常重要的,這樣開發者們就可以集中於真實的回歸上。這可以通過引入置信區間的概念來提公升,並在訊雜比過高時發出警報。針對不同的端點,變化的閾值也可以設定為不同值。

通過更改 gev 來探測 cpu 回歸的乙個限制就是我們要在 dynostats 中手動啟用這些比較的日誌輸出。當 gev 的數量逐漸增加,開發了越來越多的功能,這就不便於擴充套件了。相反,我們能夠利用乙個自動化框架來排程這些比較的日誌輸出,並對所有的 gev 進行遍歷,然後當檢查到回歸時就發出警告。

cprofile 需要一些增強以便更好地處理封裝函式以及它們的子函式。

鑑於我們在為 instagram 的 web service 構建效率框架中所投入的工作,所以我們對於將來使用 python 繼續擴充套件我們的服務很有信心。我們也開始向 python 語言本身投入更多,並且開始探索從 python 2 轉移 python 3 之道。我們將會繼續探索並做更多的實驗以繼續提公升基礎設施與開發者效率,我們期待著很快能夠分享更多的經驗。

ERP就這麼簡單

訂貨意向 妻子 當然可以,來幾個人,幾點來,想吃什麼菜?丈夫 6個人,我們7點左右回來,準備些酒 烤鴨 番茄炒蛋 冷盤 蛋花湯。你 看可以嗎?商務溝通 妻子 沒問題,我會準備好的,訂單確認 妻子記錄下需要做的選單 mps計畫 具體要準備的菜 鴨 酒 番茄 雞蛋 作 油。bom物料清單 發現需要 1只...

氣泡排序就這麼簡單

在我大一的時候自學c語言和資料結構,我當時就接觸到了氣泡排序 當時使用的是c語言編寫的 現在大三了,想要在暑假找到乙份實習的工作,又要回顧一下資料結構與演算法的知識點了。排序對我們來說是一點也不陌生了,當你打王者榮耀的時候也會有段位之分,當你打dota的時候也有天梯分。從高往下數,這個排名是有規律的...

選擇排序就這麼簡單

選擇排序 selection sort 是一種簡單直觀的排序演算法。它的工作原理是每一次從待排序的資料元素中選出最小 或最大 的乙個元素,存放在序列的起始 末尾 位置,直到全部待排序的資料元素排完。選擇排序是不穩定的排序方法 比如序列 5,5,3 第一次就將第乙個 5 與 3 交換,導致第乙個5挪動...