Linux中國

Python 中可觀測性的 7 個關鍵部分

你寫的應用會執行很多代碼,而且是以一種基本上看不到的方式執行。所以你是怎麼知道:

  • 代碼是否在運行?
  • 是不是在正常工作?
  • 誰在使用它,如何使用?

可觀測性是一種能力,可以通過查看數據來告訴你,你的代碼在做什麼。在這篇文章中,主要關注的問題是分散式系統中的伺服器代碼。並不是說客戶端應用代碼的可觀測性不重要,只是說客戶端往往不是用 Python 寫的。也不是說可觀測性對數據科學不重要,而是在數據科學領域的可觀測性工具(大多是 Juptyter 和快速反饋)是不同的。

為什麼可觀測性很重要

所以,為什麼可觀測性重要呢?在軟體開發生命周期(SDLC)中,可觀測性是一個關鍵的部分。

交付一個應用不是結束,這只是一個新周期的開始。在這個周期中,第一個階段是確認這個新版本運行正常。否則的話,很有可能需要回滾。哪些功能正常運行?哪些功能有細微的錯誤?你需要知道發生了什麼,才能知道接下來要怎麼做。這些東西有時候會以奇怪的方式不能正常運行。不管是天災,還是底層基礎設施的問題,或者應用進入了一種奇怪的狀態,這些東西可能在任何時間以任何理由停止工作。

在標準 SDLC 之外,你需要知道一切都在運行中。如果沒有,有辦法知道是怎麼不能運行的,這是非常關鍵的。

反饋

可觀測性的第一部分是獲得反饋。當代碼給出它正在做什麼的信息時,反饋可以在很多方面提供幫助。在模擬環境或測試環境中,反饋有助於發現問題,更重要的是,以更快的方式對它們進行分類。這可以改善在驗證步驟中的工具和交流。

當進行 金絲雀部署 canary deployment 或更改特性標誌時,你需要知道是否要繼續,還是等更長時間,或者回滾,反饋就顯得很重要了。

監控

有時候你懷疑有些東西不太對。也許是一個依賴服務有問題,或者是社交網站爆出了大量你的網站的問題。也許在相關的系統中有複雜的操作,然後你想確保你的系統能完美處理。在這些情況下,你就想把可觀測性系統的數據整合到控制面板上。

當寫一個應用的時候,這些控制面板需要是設計標準的一部分。只有當你的應用能把數據共享給這些控制面板,它們才會把這些數據顯示出來。

警報

看控制面板超過 15 分鐘就像看著油漆變干一樣。任何人都不應該遭受這種折磨。對於這種任務,我們要有報警系統。報警系統將可觀測性數據與預期數據進行對比,當它們不匹配的時候就發出通知。完全深入研究時間管理超出了本文的範圍。然而,從兩方面來說,可觀測應用是 報警友好的 alert-friendly

  • 它們有足夠多,足夠好的數據,發出的警報才是高質量的。
  • 警報有足夠的數據,或者接收者可以很容易的得到數據,這樣有助於找到源頭。

高質量警報有三個特點:

  • 較少的錯報:如果有警報,那一定是有問題了。
  • 較少的漏報:如果有問題,那一定有警報觸發。
  • 及時性:警報會迅速發出以減少恢復時間。

這三個特點是互相有衝突的。你可以通過提高監測的標準來減少錯誤警報,代價是增加了漏報。你也可以通過降低監測的門檻來減少漏報,代價是增加錯報。通過收集更多數據,你也可以同時減少錯報和漏報,而代價是降低了及時性。

同時改善這三個參數就更難了。這就要求高質量的可觀測性數據。更高質量的數據可以同時改善這三個特點。

日誌

有的人喜歡嘲笑用列印來調試的方法。但是,在一個大多數軟體都不在你本機運行的世界裡,你所能做的只有列印調試。日誌記錄就是列印調試的一種形式。儘管它有很多缺點,但 Python 日誌庫提供了標準化的日誌記錄。更重要的是,它意味著你可以通過這些庫去記錄日誌。

應用程序要負責配置日誌的記錄方式。諷刺地是,在應用程序對配置日誌負責了多年以後,現在越來越不是這樣了。在現代容器 編排 orchestration 環境中,現代應用程序記錄標準錯誤和標準輸出,並且信任 編排 orchestration 系統可以合理的處理日誌。

然而,你不應該依賴庫,或者說,其他任何地方。如果你想讓操作的人知道發生了什麼,使用日誌,而不是列印

日誌級別

日誌記錄的一個最重要功能就是 日誌級別。不同的日誌級別可以讓你合理的過濾並分流日誌。但是這隻有在日誌級別保持一致的情況下才能做到。最後,你應該在整個應用程序中保持日誌級別的一致性。

選擇不兼容語義的庫可以通過在應用層面的適當配置來追溯修復,這隻需要通過使用 Python 中最重要的通用風格做到:getLogger(__name-_)

大多數合理的庫都會遵循這個約定。 過濾器 Filters 可以在日誌對象發出之前就地修改它們。你可以給處理程序附加一個過濾器,這個處理程序會根據名稱修改消息,使其具有合適的級別。

import logging
LOGGER=logging.getLogger(__name__)

考慮到這一點,你現在必須明確日誌級別的語義。這其中有很多選項,但是下面這些是我的最愛:

  • Error:發送一個即時警告。應用程序處於一個需要操作人員引起注意的狀態。(這意味著包含 CriticalError
  • Warning:我喜歡把這些稱作「工作時間警報」。這種情況下,應該有人在一個工作日內關注一下。
  • Info:這是在正常工作流程中發出的。如果懷疑有問題的時候,這個是用來幫助人們了解應用程序在做什麼的。
  • Debug:默認情況下,這個不應該在生產環境中出現。在模擬環境或開發環境下,可以發出來,也可以不發。如果需要更多的信息,在生產環境也可以特地被打開。

任何情況下都不要在日誌中包含 個人身份信息 Personal Identifiable Information (PII)或密碼。無論日誌級別是什麼,都是如此,比如級別更改,激活調試級別等等。日誌聚合系統很少是 PII 安全 PII-safe 的,特別是隨著 PII 法規的不斷發展(HIPAA、GDPR 等等)。

日誌聚合

現代系統幾乎都是分散式的。 冗餘 redundancy 擴展性 scaling ,有時是 管轄權 jurisdictional 需要更多的水平分布。微服務意味著垂直分布。登錄到每個機器去查看日誌已經是不現實的了。出於合理的控制原因,允許開發人員登錄到機器中會給予他們更多的許可權,這不是個好主意。

所有的日誌都應該被發到一個聚合器。有一些商業的方案,你可以配置一個 ELK 棧,或者也可以使用其他的資料庫(SQL 或則 no-SQL)。作為一個真正的低技術解決方案,你可以將日誌寫入文件,然後將它們發送到對象存儲中。有很多解決方案,但是最重要的事情是選擇一個,並且將所有東西聚合到一起。

記錄查詢

在將所有東西記錄到一個地方後,會有很多日誌。具體的聚合器可以定義如何寫查詢,但是無論是通過從存儲中搜索還是寫 NoSQL 查詢,記錄查詢以匹配源和細節都是很有用的。

指標抓取

指標抓取 Metric Scraping 是一個 伺服器拉取 server pull 模型。指標伺服器定時和應用程序連接,並且拉取指標。

最後,這意味著伺服器需要連接和找到所有相關的應用伺服器。

以 Prometheus 為標準

如果你的指標聚合器是 Prometheus,那麼 Prometheus 格式做為一個 端點 endpoint 是很有用的。但是,即使聚合器不是 Prometheus,也是很有用的。幾乎所有的系統都包含與 Prometheus 端點兼容的 墊片 shim

使用客戶端 Python 庫給你的應用程序加一個 Prometheus 墊片,這將使它能夠被大多數的指標聚合器所抓取。當 Prometheus 發現一個伺服器,它就期望找到一個指標端點。這經常是應用程序路由的一部分,通常在 /metrics 路徑下。不管 Web 應用的平台是什麼,如果你能在一個端點下運行一個定製類型的定製位元組流,Prometheus 就可以將它抓取。

對於大多數流行的框架,總有一個中間件插件或者類似的東西收集指標,如延遲和錯誤率。通常這還不夠。你需要收集定製的應用數據:比如,每個端點的緩存 命中/缺失 hit/miss 率,資料庫延遲,等等。

使用計數器

Prometheus 支持多個數據類型。一個重要且巧妙的類型就是計數器。計數器總是在前進 —— 但有一點需要注意。

當應用重置,計數器會歸零。計數器中的這些「 歷時 epochs 」通過將計數器「創建時間」作為元數據發送來管理。Prometheus 知道不去比較兩個不同 歷時 epochs 的計數器。

使用儀錶值

儀錶值會簡單很多:它們測量瞬時值。用它們來測量會上下起伏的數據:比如,分配的總內存大小,緩存大小,等等。

使用枚舉值

枚舉值對於整個應用程序的狀態是很有用的,儘管它們可以以更精細的方式被收集。比如,你正使用一個 功能門控 feature-gating 框架,一個有多個狀態(比如,使用中、關閉、 屏蔽 shadowing 等)的功能,也許使用枚舉會更有用。

分析

分析不同於指標,因為它們要對應連續的事件。比如,在網路伺服器中,事件是一個外部請求及其產生的工作。特別是,在事件完成之前事件分析是不能被發送的。

事件包含特定的指標:延遲,數量,以及可能產生的對其他服務請求的細節,等等。

結構化日誌

現在一個可能的選擇是將日誌結構化。發送事件只發送帶有正確格式的有效 載荷 payload 的日誌。這個數據可以從日誌聚合器請求,然後解析,並且放入一個合適的系統,這樣可以對它的可見性。

錯誤追蹤

你可以使用日誌來追蹤錯誤,也可以用分析來追蹤錯誤。但是一個專門的錯誤系統還是值得的。一個為錯誤而優化的系統可以發送更多的錯誤,因為錯誤畢竟還是罕見的。這樣它就可以發送正確的數據,並且用這些數據,它能做更多智能的事情。Python 中的錯誤追蹤系統通常和一般的異常處理關聯,然後收集數據,並且把它發到一個專門的錯誤聚合器。

使用 Sentry

很多情況下,自己運行 Sentry 是正確的做法。當錯誤發生時,就說明有些東西就出問題了。可靠地刪除敏感數據是不可能的,因為一定有會出現敏感數據被發送到不應該的地方。

通常,這種工作量並不會很大:異常並不常出現。最後,這個系統並不需要很高的質量,也不需要高可靠性的備份。昨天的錯誤應該已經修復了,希望如此,如果沒有,你還會發現的!

快速、安全、可重複:三者都要

可觀測的系統開發起來更快,因為它們可以給你提供反饋。它們運行起來也更安全,因為當出問題的時候,它們也會更早的讓你知道。最後,因為有反饋迴路,可觀測性也有助於圍繞它構建可重複的過程。可觀測性可以讓你了解你的應用程序。而更了解它們,就勝利了一半。

磨刀不誤砍柴功

構建所有的可觀測層是一件困難的事情。總會讓人感覺是在浪費的工作,或者更像是「可以有,但是不急」。

之後再做這個可以嗎?也許吧,但是不應該。正確的構建可觀測性可以加速後面所有階段的開發:測試、監控,甚至是培訓新人。在一個和科技行業一樣動蕩的行業,減少培訓新人的工作量絕對是值得的。

事實上,可觀測性很重要,所以儘早把它寫出來,然後就可以在整個過程中進行維護。反過來,它也會幫你維護你的軟體。

via: https://opensource.com/article/21/11/observability-python

作者:Moshe Zadka 選題:lujun9972 譯者:MCGA 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國