自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Facebook 如何避免大規(guī)模線上故障

新聞 前端
為了能在快速變更的系統(tǒng)中使 FB 的系統(tǒng)穩(wěn)定,工程師們對系統(tǒng)故障進行了一些總結和抽象,為了能夠建立可靠的系統(tǒng)必須要理解故障。

Fail at Scale 是 Facebook 2015 年在 acm queue 上發(fā)表的一篇文章。主要寫了常見的線上故障和應對方法,內容還是比較實在的。

"What Would You Do If You Weren't Afraid?" 和 "Fortune Favors the Bold." 是 FB 公司信條,掛墻上那種。

為了能在快速變更的系統(tǒng)中使 FB 的系統(tǒng)穩(wěn)定,工程師們對系統(tǒng)故障進行了一些總結和抽象,為了能夠建立可靠的系統(tǒng)必須要理解故障。而為了理解故障,工程師們建立了一些工具來診斷問題,并建立了對事故進行復盤,以避免未來再次發(fā)生的文化。

事故的發(fā)生可以被分為三大類。

為什么會發(fā)生故障

單機故障

通常情況下,單機遇到的孤立故障不會影響到基礎設施的其他部分。這里的單機故障指的是:一臺機器的硬盤出現了故障,或者某臺機器上的服務遇到了代碼中的錯誤,如內存損壞或死鎖。

避免單個機器故障的關鍵是自動化。通過總結已知的故障模式,并與探究未知的故障癥狀相結合。在發(fā)現未知故障的癥狀(如響應緩慢)時,將機器摘除,線下分析,并將其總結至已知故障中。

工作負載變化

現實世界的重大事件會對 Facebook 網站基礎設施帶來壓力,比如:

  • 奧巴馬當選總統(tǒng),他的 Facebook 頁面經歷了創(chuàng)紀錄的活動水平。

  • 重大體育賽事的高潮部分,如超級碗或世界杯,會導致極高的帖子數量。

  • 負載測試,以及新功能發(fā)布時的引流階段會不向用戶展示但引入流量。

這些事件中收集到的統(tǒng)計數據會為系統(tǒng)設計提供獨特的視角。重大事件會導致用戶行為變化,這些變化能為系統(tǒng)后續(xù)的決策提供數據依據。

人為錯誤

圖 1a 顯示了周六和周日發(fā)生的事故是如何大幅減少的,盡管網站的流量在整個一周內保持一致。圖 1b 顯示了在六個月的時間里,只有兩個星期沒有發(fā)生事故:圣誕節(jié)的那一周和員工要為對方寫同行評論的那一周。

上圖說明大部分故障都是人為原因,因為事件的統(tǒng)計與人的活動規(guī)律是一致的。

故障的三個原因

故障的原因很多,不過有三種最為常見。這里列出的每一種都給出了預防措施。

快速部署的配置變更

配置系統(tǒng)往往被設計為在全球范圍內快速復制變化??焖倥渲米兏?強大的工具,然而,快速配置變更可能導致部署問題配置時發(fā)生事故。下面是一些防止配置變更故障的手段。

所有人公用同一套配置系統(tǒng)。使用一個共同的配置系統(tǒng)可以確保程序和工具適用于所有類型的配置。

配置變化靜態(tài)檢查。許多配置系統(tǒng)允許松散類型的配置,如 JSON 結構。這些類型的配置使工程師很容易打錯字段的名稱,在需要使用整數的地方使用字符串,或犯其他簡單的錯誤。這類簡單的錯誤最好用靜態(tài)驗證來捕捉。結構化格式(Facebook 使用 Thrift)可以提供最基本的驗證。然而,編寫程序來對配置進行更詳細的業(yè)務層面的驗證也是應該的。

金絲雀部署。將配置先部署到小范圍,防止變更造成災難性后果。金絲雀可以有多種形式。最簡單的是 A/B 測試,如只對 1% 的用戶啟用新的配置。多個 A/B 測試可以同時進行,可以使用一段時間的數據來跟蹤指標。

就可靠性而言,A/B 測試并不能滿足所有需求。

  • 一個被部署到少數用戶的變更,如果導致相關服務器崩潰或內存耗盡,顯然會產生超出測試中有限用戶的影響。

  • A/B 測試也很耗費時間。工程師們經常希望在不使用 A/B 測試的情況下推送小的變化。

為了避免配置導致的明顯問題,Facebook 的基礎設施會自動在一小部分服務器上測試新版本的配置。

例如,如果我們希望向 1% 的用戶部署一個新的 A/B 測試,會首先向 1% 的用戶部署測試,保證這些用戶的請求落在少量服務器上,并對這些服務器進行短時間的監(jiān)控,以確保不會因為配置更新出現非常明顯的崩潰問題。

堅持可以運行的配置。配置系統(tǒng)設計方案保證在發(fā)生失敗時,保留原有的配置。開發(fā)人員一般傾向于配置發(fā)生問題時系統(tǒng)直接崩潰,不過 Facebook 的基礎設施開發(fā)人員認為用老的配置,使模塊能運行比向用戶返回錯誤好得多。(注:我只能說這個真的要看場景)

配置有問題時回滾要快速。有時,盡管盡了最大努力,有問題的配置還是上了線。迅速回滾是解決這類問題的關鍵。配置內容在版本管理系統(tǒng)中進行管理,保證能夠回滾。

強依賴核心服務

開發(fā)人員傾向于認為,核心服務:如配置管理、服務發(fā)現或存儲系統(tǒng),永遠不會失敗。在這種假設下,這些核心服務的短暫故障,會變成大規(guī)模故障。

緩存核心服務的數據。可以在服務本地緩存一部分數據,這樣可以降低對緩存服務的依賴。  提供專門 SDK 來使用核心服務。 核心服務最好提供專門的 SDK,這樣保證大家在使用核心服務時都能遵循相同的最佳實踐。同時在 SDK 中可以考慮好緩存管理和故障處理,使用戶一勞永逸。  進行演練。 只要不進行演練,就沒法知道如果依賴的服務掛了自己是不是真的會掛,所以通過演練來進行故障注入是必須的。

延遲增加和資源耗盡

有些故障會導致延遲增加,這個影響可以很小(例如,導致 CPU 使用量微微增加),也可以很大(服務響應的線程死鎖)。

少量的額外延遲可以由 Facebook 的基礎設施輕松處理,但大量的延遲會導致級聯故障。幾乎所有的服務都有一個未處理請求數量的限制。這個限制可能是因為請求響應類服務的線程數量有限,也可能是由于基于事件的服務內存有限。如果一個服務遇到大量的額外延遲,那么調用它的服務將耗盡它的資源。這種故障會層層傳播,造成大故障。

資源耗盡是特別具有破壞性的故障模式,它會使請求子集所使用的服務的故障引起所有請求的故障:

一個服務調用一個新的實驗性服務,該服務只向 1% 的用戶推出。通常情況下,對這個實驗性服務的請求需要 1 毫秒,但由于新服務的失敗,請求需要 1 秒。使用這個新服務的 1% 的用戶的請求可能會消耗很多線程,以至于其他 99% 的用戶的請求都無法被執(zhí)行。

下面的手段可以避免請求堆積:

  • 延遲控制。在分析過去涉及延遲的事件時,工程師發(fā)現大量請求都是堆積在隊列中等待處理。服務一般會有線程數或內存使用上的限制。由于服務響應速度 < 請求傳入速度,隊列會越來越大,直到達到閾值。想要在不影響正常運行可靠性的前提下限制隊列大小,FB 工程師研究了 bufferbloat 問題,這里的問題和 bufferbloat 問題很類似,都是在擁塞的時候不引起過度延遲。這里實現了 CoDel(controlled delay 縮寫)算法的一個變種:

注:雖然里面寫著 M 和 N,但其實 M 和 N 是定值,N = 100ms,M = 5ms

  1. onNewRequest(req, queue): 
  2.  
  3.   if queue.lastEmptyTime() < (now - N seconds) { 
  4.      timeout = M ms 
  5.   } else { 
  6.      timeout = N seconds; 
  7.   } 
  8.   queue.enqueue(req, timeout) 

在這個算法中,如果隊列在過去的 100ms 內沒有被清空,那么在隊列中花費的時間被限制在 5ms。如果服務在過去的 100ms 能夠清空隊列,那么在隊列中花費的時間被限制為 100 ms。這種算法可以減少排隊(因為 lastEmptyTime 是在遙遠的過去,導致 5ms 的排隊超時),同時允許短時間的排隊以達到可靠性的目的。雖然讓請求有這么短的超時似乎有悖常理,但這個過程允許請求被快速丟棄,而不是在系統(tǒng)無法跟上傳入請求的速度時堆積起來。較短的超時時間可以確保服務器接受的工作總是比它實際能處理的多一點,所以它永遠不會閑置。

前面也說了,這里的 M 和 N 基本上不需要按場景調整。其他解決排隊問題的方法,如對隊列中的項目數量設置限制或為隊列設置超時,需要按場景做 tuning。M 固定 5 毫秒,N 值為 100 毫秒,在大多場景下都能很好地工作。Facebook 的開源 Wangle 庫和 Thrift 使用了這種算法。

  • 自適應 LIFO(后進先出)。大多數服務以 FIFO 的順序處理隊列。然而,在大量排隊期間,先入的請求往往已經等了很久,用戶可能已經放棄了請求相關的行為。這時候處理先入隊的請求,會將資源耗費在一個不太可能使用戶受益的請求上。FB 的服務使用自適應后進先出的算法來處理請求。在正常的操作條件下,請求是 FIFO 處理模式,但是當隊列開始任務堆積時,則切換至 LIFO 模式。如圖 2 所示,自適應 LIFO 和 CoDel 可以很好地配合。CoDel 設置了較短的超時時間,防止了形成長隊列,而自適應 LIFO 模式將新的請求放在隊列的前面,最大限度地提高了它們滿足 CoDel 設置的最后期限的機會。HHVM 實現了這個后進先出算法。

  • 并發(fā)控制。CoDel 和自適應 LIFO 都在服務器端運行。服務端是降低延遲的最佳場所--server 為大量的 client 服務,且有比 client 端更多的信息。 不過有些故障較嚴重, 可能 導致服務端的控制無法啟動。 為了兜底 FB 還在客戶端實施了一個策略: 每個客戶端都會在每個服務的基礎上跟蹤未完成的出站請求的數量。 當新的請求被發(fā)送時,如果對該服務的未決請求的數量超過可配置的數量,該請求將立即被標記為錯誤( 注:應該類似熔斷 )。 這種機制可以防止單一服務壟斷其客戶的所有資源。

幫助診斷故障的工具

盡管有最好的預防措施,故障還是會發(fā)生。故障期間,使用正確的工具可以迅速找到根本原因,最大限度地減少故障的持續(xù)時間。

使用 Cubism 的高密度儀表板在處理事故時,快速獲取信息很重要。好的儀表盤可以讓工程師快速評估可能出現異常的指標類型,然后利用這些信息來推測根本原因。然而儀表盤會越來越大,直到難以快速瀏覽,這些儀表盤上顯示的圖表有太多線條,無法一目了然,如圖3所示。

為了解決這個問題,我們使用 Cubism 構建了我們的頂級儀表盤,這是一個用于創(chuàng)建地平線圖表的框架--該圖表使用顏色對信息進行更密集的編碼,允許對多個類似的數據曲線進行輕松比較。例如,我們使用 Cubism 來比較不同數據中心的指標。我們圍繞 Cubism 的工具允許簡單的鍵盤導航,工程師可以快速查看多個指標。圖 4 顯示了使用面積圖和水平線圖的不同高度的同一數據集。在面積圖版本中,30像素高的版本很難閱讀。同一高度下地平線圖非常容易找到峰值。

最近發(fā)生了什么變更?

由于失敗的首要原因之一是人為錯誤,調試失敗的最有效方法之一是尋找人類最近的變化。我們在一個叫做 OpsStream 的工具中收集關于最近的變化的信息,從配置變化到新版本的部署。然而,我們發(fā)現隨著時間的推移,這個數據源已經變得非常嘈雜。由于數以千計的工程師在進行改變,在一個事件中往往有太多的改變需要評估。

為了解決這個問題,我們的工具試圖將故障與其相關的變化聯系起來。例如,當一個異常被拋出時,除了輸出堆棧跟蹤外,我們還輸出該請求所讀取的任何配置的值最近發(fā)生的變化。通常,產生許多錯誤堆棧的問題的原因就是這些配置值之一。然后,我們可以迅速地對這個問題做出反應。例如,讓上線該配置的工程師趕緊回滾配置。

從失敗中學習

失敗發(fā)生后,我們的事件審查過程有助于我們從這些事件中學習。

事件審查過程的目的不是為了指責。沒有人因為他或她造成的事件被審查而被解雇。審查的目的是為了了解發(fā)生了什么,補救使事件發(fā)生的情況,并建立安全機制以減少未來事件的影響。

審查事件的方法 Facebook 發(fā)明了一種名為 DERP(detection, escalation, remediation, and prevention)的方法,以幫助進行富有成效的事件審查。

  • 檢測 detection。如何檢測問題--報警、儀表板、用戶報告?

  • 升級 escalation。正確的人是否迅速介入?這些人是否可以通過警報被拉進故障處理流程,而不是人為拉進來?

  • 補救 remediation。采取了哪些步驟來解決這個問題?這些步驟是否可以自動化?

  • 預防 prevention。哪些改進可以避免同類型的故障再次發(fā)生?你如何能優(yōu)雅地失敗,或更快地失敗,以減少這次故障的影響?

在這種模式的幫助下,即使不能防止同類型的事件再次發(fā)生,也至少能夠在下一次更快恢復。

一把梭的時候少出故障

"move fast" 的心態(tài)不一定與可靠性沖突。為了使這些理念兼容,Facebook 的基礎設施提供了安全閥:

  • 配置系統(tǒng)可以防止不良配置的快速部署;

  • 核心服務為客戶提供加固 SDK 以防止故障;

  • 核心穩(wěn)定性庫可以防止在延遲發(fā)生的情況下資源耗盡。

為了處理漏網之魚,還建立了易于使用的儀表盤和工具,以幫助找到與故障關聯的最近的變更。

最重要的是,在事件發(fā)生后,通過復盤學到的經驗將使基礎設施更加可靠。

References

  1. CoDel (controlled delay) algorithm; http://queue.acm.org/detail.cfm?id=2209336.

  2. Cubism; https://square.github.io/cubism/.

  3. HipHop Virtual Machine (HHVM); https://github.com/facebook/hhvm/blob/43c20856239cedf842b2560fd768038f52b501db/hphp/util/job-queue.h#L75.

  4. Thrift framework; https://github.com/facebook/fbthrift.

  5. Wangle library; https://github.com/facebook/wangle/blob/master/wangle/concurrent/Codel.cpp.

  6. https://github.com/facebook/folly/blob/bd600cd4e88f664f285489c76b6ad835d8367cd2/folly/executors/Codel.cpp

 

責任編輯:張燕妮 來源: TechPaper
相關推薦

2017-09-27 13:56:58

微服務架構故障網絡

2009-04-09 09:32:00

VoWLANWLAN

2010-09-01 15:16:49

WLAN交換機結構

2014-06-20 10:04:28

Facebook宕機

2017-02-28 19:27:22

Facebook開源Prophet

2021-04-24 20:22:57

數據泄露Facebook數據保護

2023-11-24 13:24:14

CIOOptus

2021-10-07 16:45:44

存儲網絡場景

2017-05-05 11:18:59

2021-04-19 09:37:12

RocketMQ集群版本

2023-02-21 10:58:01

2025-02-05 11:30:00

單點故障MySQL數據庫

2022-06-09 14:35:07

網絡釣魚網絡攻擊

2016-01-29 20:23:23

華為

2017-04-26 13:30:24

爬蟲數據采集數據存儲

2024-07-03 08:19:56

2014-07-14 10:25:36

虛擬運營商

2019-11-14 09:17:05

TiDB分庫分表性能

2018-03-26 11:14:13

程序猿bug代碼

2018-06-28 09:12:37

阿里云故障運維
點贊
收藏

51CTO技術棧公眾號