閱讀995 返回首頁    go 阿裏雲 go 技術社區[雲棲]


超全總結 | 阿裏如何應對電商故障?神秘演練細節曝光

近日,在 QCon北京2017大會上,來自阿裏巴巴中間件團隊的技術專家周洋(花名中亭)發表了題為《阿裏電商故障治理和故障演練實踐》專題演講。在會後官方組織的評選中,本次演講的內容得到了一致好評,中亭獲選為本次大會的明星講師。此次演講整體上分享了從 2011 年至今,阿裏巴巴電商平台遇到的諸多有代表性的故障,以及在此過程中積累的非常多的高可用保障經驗和解決方案。

image


演講內容包括兩大部分:第一部分會從分布式係統經典依賴故障出發,剖析故障成因,介紹治理方案和技術演進;第二部分從宏觀視角探討構建一套"防故障"設施的重要性,並探討如何設計一套故障演練係統,介紹故障演練的基本原則和經驗總結。

演講全文:

大家好,今天來的人不少,可見對於故障耿耿於懷的人,不止我自己。今天分享的內容主要還是圍繞故障治理有關。眾所周知,故障治理本身就是一個比較大的話題,幾乎涉及到運維、研發、故障運行管理的全部崗位,奇葩一點的故障還可能涉及到運營和產品經理。聊到故障的苦與淚,相信45分鍾絕對連開頭都沒講完。今天的分享,主要還是回歸故障發生的本質,故障原因角度切入。看是否有一些方法論和通用性的手段可以沉澱出來。希望可以對大家有所幫助。

今天演講的主要包括兩個部分:第一部分會從分布式係統經典依賴故障出發,剖析故障成因,介紹治理方案和技術演進;第二部分從宏觀視角探討構建一套"防故障"設施的重要性,並探討如何設計一套故障演練係統,介紹故障演練的基本原則和最佳經驗。考慮演講時間和內容關聯度,之前報給大會提綱中的"通過灰度發布提前發現故障"的章節被隱去,有興趣的同學可以會後找我單獨交流。

image


首先介紹一下我自己,姓名周洋,花名中亭。2011年加入阿裏接觸穩定性技術領域,開始做一些穩定性產品的研發,同時也會承擔一些架構演進的推進工作,比如HTTPS改造,電商交易鏈路升配等。2015年開始搞雙11大促,做為共享事業部的大促負責人,保障了雙11的穩定。也獲得雙11老A也就是雙11特種兵的稱號。

共享事業部對於在座各位可能比較陌生。如果我換一個說法,商品、交易、會員、優惠、評價、中間件,大家應該就都知道了,這是雙11當天最具挑戰的鏈條之一。右邊是中間件核心作戰室成員,在過了雙11業務高峰後的一張合影。2016年至今,工作的重點在常態穩定性的確定性方麵,今天的分享也是主要圍繞這部分內容。

首先拋一個問題,什麼情況下你會認為淘寶網掛了? 我相信關注這個問題的人很多,不過能給出確切答案的人並不多。因為這個看似簡單的問題,真要回答起來好像也不是那麼容易。今天的分享,我先試著給大家回答一下這個問題。

image


讓我們從一張“簡單”的頁麵說起。這張頁麵叫做商品詳情頁,相信在座的各位對這張頁麵不會陌生,因為對於大部分人來講,這張頁麵是他們在淘寶完成一筆訂單的第一步。而商品詳情頁的使命就是把商品的信息沒有保留的展示給大家,引起大家的興趣,引導大家完成購買或是收藏。從信息展示的角度來講,商品詳情頁確實是一張非常簡單的頁麵。

image


我們再來看一下商品詳情頁應用的後台架構。商品詳情頁是阿裏最早實現靜態化應用之一。那些與瀏覽者無關信息,比如商品標題、圖片信息、銷售屬性組合等信息均直接進入緩存,其他和用戶相關的,如優惠、庫存、物流、服務等動態信息則通過異步調用方式填充至靜態化後的頁麵框架內。為了在一張頁麵展示足夠多可供決策信息,撩起用戶的購買欲望,詳情後台必須去依賴非常多的服務應用,聚合足夠多的信息。少則幾十,多則成百。從這個角度來講,商品詳情頁麵又是阿裏依賴最複雜的應用之一。

互聯網業務的一個主要特點是,業務迭代非常快,每天有新需求,每周都有新發布,每年都有大重構,每一次變化都有可能導致狀況的發生。越是貼近用戶的係統,受下遊服務影響越大。那麼我們不僅好奇,對於詳情這個阿裏最複雜的應用,下遊發生一些狀況時,係統會變成怎樣?我們通過兩個實驗來觀察一下:

實驗一:假設後端的優惠、庫存、物流發生故障,我們來觀察一下商品詳情頁的表現。

image


乍一看,好像沒什麼問題。隻是覺得頁麵清爽了一些。或許在這個信息過暴的時代,看著這麼清新脫俗的頁麵,還有一點點暗爽。

在現場做了兩個調查,觀察大家對實驗一的反映。調查1是請認為詳情頁故障了的同學請舉手。結果是現場沒有人舉手(也可能是現場氛圍還比較冷);調查2是請大家來找茬,前後兩個詳情頁有多少處不同?這次有一個妹子說出了正確的答案(同時也向妹子贈送了電子工業出版社出版的講述阿裏雙11技術演進的《盡在雙11》書籍)。

image


沒有對比就沒有傷害,一共有6處不同。從功能角度,這鐵定是一個故障頁麵。不過從用戶體驗和業務角度講,少了這些信息也不影響商品購買,不影響核心用戶體驗。好像又是沒故障?有點糾結,對吧? 您先糾結一會兒,我們來進行第二個實驗。

實驗二:當商品詳情的"商品"出了問題,商品詳情會怎樣?

image


詳情還是那個詳情,隻不過是商品詳情變成了錯誤詳情。第一張頁麵:很抱歉,你查看的商品找不到了。有可能是你訪問的方式不對,比如URL上麵少了一些參數,也可能是後台真的出問題,對於用戶還算是比較溫柔的一種方式。第二張頁麵:很可能就是網站真的出問題了。比較可能的原因是後台沒有合理的處理超時導致前端異常。不過說實話,這個頁麵我也非常少的見到。如果真的出現了,那基本就是一次非常嚴重的事故。

image


通過上麵的兩個實驗,相信大家應該對於我們今天要介紹的一個概念"強弱依賴"有一些模煳的感覺了。 從感性的角度來講,就是當下遊依賴服務出現問題時,當前係統會受到一些影響,讓用戶有感覺的是強依賴,沒感覺的是弱依賴。不過這種定義不夠嚴謹,因為總不能說沒有用戶訪問時,就不算故障吧。所以也需要從理性角度定義一下:首先應該發生狀況,其次應該是核心業務,最後是否帶來損失。不影響核心業務流程,不影響係統可用性的依賴都可以叫做弱依賴,反之就是強依賴。

image


終於解釋清楚什麼是強弱依賴,那麼做好強弱依賴治理到底有什麼意義?拋開依賴模型來看強弱,意義不大。嚴謹的依賴模型應該包括關係、流量、強弱三個組成部分。依賴關係定義依賴的方向,我依賴誰,誰依賴我。流量定義著每個應用、服務、方法調用的次數,強弱則定義著依賴的鬆緊程度。依賴治理就是通過科學的手段持續穩定地拿到關係、流量、強弱的數據。強弱依賴主要可以被應用到下麵的場景:

• 係統改造驗收:對於分布式係統,至少應該做到運行態中不會因為我依賴的係統出現故障,而引起當前應用出現可用性的問題,比如進程掛掉,頻繁FullGC,負載飆高等,何時何地都具備快速止血的能力。
• 限流降級參考:對於弱依賴,一般都要配置限流或是自動降級策略,比起通過拍腦袋或是經驗值來設定,倒不如通過實際的故障測試來進行微調,比如對於下遊出現超時情況,就可以通過實驗得出基於線程池限流到底要填寫多少數值。
• 應用啟動順序:理想情況下,應用啟動更應該做到0強依賴啟動。不過有一些情況無法做到。因此應用啟動的依賴順序也需要實時關注。特別是新IDC、機房建站時,那個蜘蛛網一樣的依賴關係,最好是通過係統方式獲得。
• 故障根源定位:後台係統的故障,往往通過上一層的業務故障表現出來。故障處理講究的是爭分多秒,良好的強弱依賴,對於係統自動化診斷有非常大的助力作用。
• 依賴容量評估:正常調用鏈路下係統容量需要評估,當某個弱依賴掛掉時,整體的容量是否有變化。

說完背景,終於可以聊一下強弱依賴的技術實現。在阿裏,強弱依賴的技術演進整體上分了3個階段,每個階段的方案的誕生都有其獨特的時代背景和業務難點。現在回頭看來,也可以看到當時技術的局限性和突破。

image


熟悉淘寶技術發展史的同學都知道,2008年阿裏剛剛完成一個代號為五彩石的項目,完成從巨石係統向服務化係統的改造。業務和開發模式上有了較大的發展,不過網狀的依賴關係也帶來了非常多的問題。這個紀元的主要特點是:故障頻發,技術思路和方法都是以結果為導向,糙一點、結果精度差一點可以忍受。

模擬依賴故障技術上有三招,改代碼+發布,遠程Debug+重啟,登陸機器去執行一些shell命令操作。 好處是靈活隨意,可以一定程度達到效果;壞處是成本高,影響環境穩定,你測試的時候其他人處於無法工作狀態,影響效率。此外,這個階段,因為分布式鏈路追蹤技術還沒起步,所以模擬依賴故障時,經常會漏掉一些主機或某些服務。故障的粒度也比較粗,對於一些Linux的命令,都是主機級別的。

阿裏內部有一套日常環境,主要做上線前的集成測試。為了盡量減少對環境的影響。我們通過修改服務版本的方式,形成一個獨立的測試環境。記得11年下半年,我開始做第一版的時候,我搭了淘寶12個核心應用的日常環境,踩坑無數,純體力活,也算前無古人,後無來者了。

通過這套環境跑了幾次結果,發給核心的業務TL,大家很興奮,貌似找到一條治理的路子。不過很快暴露了新問題,比如環境的運維歸屬問題,開發機器的幹擾問題,以及對於業務的了解程度和測試粒度問題,所以在很長一段時間測試的範圍都局限在交易核心鏈路。

image


第二個階段的核心就是提效,從第一個階段的痛點入手,解決人的成本和環境的問題。這個階段之後,基本可以擺脫手工方式,效率上有大幅度提升。

這個階段也引入了一些測試技術,其中用的比較多的是Selenium,通過這種技術可以提前錄製用戶行為並轉化為測試腳本,並且每一個步驟都可以截圖記錄,方便問題複查。

在這個時期,阿裏中間件的技術有一定發展,分布式追蹤技術出現,可以把用戶訪問的鏈條串聯起來,排查問題的效率有了一定提升。同時所有的中間件,如Nginx、消息、分布式服務調用、分布式數據庫、軟負載和配置中心等都做了改造,支持用戶流量的標記、追蹤和路由控製。基於上述這些技術進展,環境的問題就有非常大的突破。

在內部我們稱為叫二套環境。它的核心原理是在基礎環境之上,動態區分出一些小環境,他們分別是某個業務的子集。項目之間彼此獨立,不會互相調用,隻有當依賴的服務不在時,才會去訪問基礎環境的服務。數據庫和緩存是公用的。

在這個階段,我們不必再去修改代碼的服務版本,每次發布後,代碼的版本等能夠自動化的保持一致,運維成本有所降低,野服務幹擾的情況也有所緩解,人的介入非常的少。不過還是有一些問題亟待解決:首先,二套環境的路由策略是和用戶綁定的,也就是說需要提前去做一些配置;其次,域名上也有一些限製,加了second等前綴,測試路徑中URL等複用率低的問題沒有完全解決;第三,測試的粒度仍然很粗,獨占機器,規模化推廣時,機器成本和用例運行的成本還是很高;第四,故障場景缺失,隻存在於基礎環境的服務沒法模擬的故障,如:數據庫故障,緩存故障等。

image


2014年的時候,我們的思維方式有了比較大的突破。我們不再糾結於環境和外部手段的改進,而是回歸到強弱依賴關注最核心的部分。那就是業務影響和係統設計。能否實現一種隻與代碼設計和業務相關,而與外部環境無關的方案呢?

這期間有兩個關鍵思路或是推論:

推論1:我們要的是下遊依賴出現故障現象,不必真的是下遊服務提供方出現故障。隻要消費方感覺下遊出現故障即可。從這個思路來講,商品詳情如果要做強弱依賴測試,隻要自己玩就OK,不需要去折騰下遊依賴的幾十個應用。

推論2:我們之所以需要單獨搭建環境,為的就是控製故障的影響範圍。那麼我們可以換一下思路,就是我們隻影響要發生故障的請求,其他的業務流量都放過。是不是就可以達到目的。本質上是一種對業務流量的篩查能力。

有了上麵的思路,第一問題就是如何攔截用戶的請求?攔截用戶請求,讓用戶改造成本最低,沒有什麼地方比中間件更適合了。每個通用的遠程調用接口,都是可以做文章的點,並且中間件之上的業務係統不用做任何改造。

下一個問題就是故障規則和業務識別,我們曾考慮在用戶請求的入口就打上標記,置入故障規則,不過發現對於post請求,異步js請求,定時任務等都有比較大的改造成本,且有安全隱患。 所以就增加了一個服務端,直接下發故障規則到依賴插件上。故障插件通過對流量的調用攔截+業務識別,唯一確定影響哪一個請求,然後通過故障規則判斷是注入異常還是超時,從而達到模擬故障的效果。 因為插件可擴展的設計,所以我們默認是可以同時注入多種故障場景的,同時插件也會把影響到請求的詳細信息異步上報給服務端做分析。

理論上通過上述的方案,在業務流量輸入方麵,我們沒有任何要求。無論是人的自發測試行為,還是機器的測試行為,都沒有任何限製。隻不過為最大限度複用已有的測試用例積累,提高自動化程度,我們設計了一套用例注解,封裝了和強弱依賴服務端的通信。利用Junit生命周期的特點,完成故障規則的下發和清除。任何一個測試用例,20秒之內改造成一個強弱依賴的測試用例。在結果輸出方麵,會詳細的展示一次強弱依賴檢測的過程,以及測試用例涉及到的鏈路的依賴變化。到此階段,強弱依賴真正達到了一個相對裏程碑的版本,2014年開始,強弱依賴也作為雙11必做的一個橫向項目。

下麵是強弱依賴注解和依賴係統的示例:

image
image


總的來說,整個強弱依賴技術演進曆史,就是對數據準確性,穩定性,成本、效率的不懈追求,並在這幾者之間達成一個動態平衡。

眾所周知,2017年不大太平,業界出現了很多大故障。


image


2017年3月1日,弗吉尼亞州數據中心出現故障,亞馬遜S3 服務出現了較高的錯誤率,直接影響到成千上萬個在線服務;2017年1月31日, GibLab同學線上數據庫變更時,遇到突發了一個情況。因為操作失誤,導致整個生產數據庫被誤刪除,丟失6個小時的數據;

2017年2月份國內的一家經常被用來測試網絡連通性的友商也出現了故障,工信部迅速關注,並緊急約談了相關公司。同時下發緊急通知要求BAT等各重點互聯網企業吸取教訓,業界一片嘩然。

這時候,有一家公司顯得特別淡定,那就是Netflix。 Netflix是一家服務全球的在線影片租賃提供商,他的核心業務完全架設在AWS上麵。據新聞揭露,Netflix在亞馬遜故障時可以很快的恢複正常,因為他們內部有一個"防故障"的基礎設施。聽起來,好像是我們需要的東西。

image


深入調查之後,發現防故障基礎設施背後是一個猴子軍團。

早在2012年,Netflix就發布了Chaos Monkey。用來在隨機殺死實例,據官方數據指出,到目前累計殺死65,000個節點。他們的測試策略也比較有趣:在工作時間在生產和測試環境運行,目標測試係統的健壯性,訓練後備人員,讓恢複更簡潔、快速、自動;Latency Monkey的作用就是讓某台機器的請求或返回變慢,觀察係統的表現; Chaos Gorilla的能力是搞掛一個機房,宏觀驗證業務容災和恢複的能力。Netflix發布猴子軍團的原因是因為,他們很早就吃過雲故障的虧,所以本能是認為雲設施是不可靠的,必須在通過演練來驗證軟件層麵的容災。

image


古代有個哲學家說過"沒有人曾經兩次踏進同一條河流",因為無論是這條河還是這個人都已不同。故障也是類似的,故障發生的時間地點,影響流量,與故障打交道的人都沒法完全相同。從這個角度看,故障治理本身是一個偽命題,都是在解決過去某一個時刻的問題。不過從程序員視角(我習慣叫上帝視角),任何故障的原因都是可被定位的,避免相同原因重複引發故障,是每個程序員應該執著追求的目標。電商曆史上遇到了非常多有代表性的故障,為了不讓故障重複發生,阿裏內部也打造了一套"防故障"的基礎設施。

image


2015年5月27日,因為光纖中斷的問題,支付寶大規模宕機事故,公司內部得出一個結論:任何基礎設施、生產係統、任何流程都可能出現問題,沒有經過重大災難驗證的容災設施都是耍流氓。 啟動了代號為虎虎虎的生產突襲項目,用來驗證異地多活的質量。

2012年,完成交易的同城雙活後,就啟動了同城容災演練,也叫斷網演練。驗證核心係統的同城一個機房掛掉的情況下,是否還可以正常工作。

2011年,開始做強弱依賴的治理和建設,希望提前發現因為依賴問題導致的係統故障,係統的代號是EOS(出處是古希臘神話中的黎明女神,語意是能夠把紛亂的依賴關係梳理清楚)。

可以看到,這三大件和Netflix的猴子軍團從功能上基本上是對標的。那是不是就應該沒有故障,安枕無憂了呢? 答案鐵定不是。

image


理想很豐滿,現實很骨感。阿裏巴巴因為其多元化的業務場景和日益複雜的技術架構,會遇到各式各樣的故障,故障治理的難度相比流媒體服務故障治理,難度是也增量了幾個台階。前麵介紹過的強弱依賴和容災演練隻能覆蓋到部分故障。如果對故障整體做初步畫像,故障整體可以分為IaaS層、PaaS層、SaaS層的故障,每一層都可能有很多故障觸發原因和表現。那麼對於這麼多種類繁雜的故障,內心一定是懵逼的。我們要如何重現,進而避免這麼多繁雜的故障呢?

image


熟悉三體的同學應該聽說過"降維攻擊"這個詞,不妨讓我們把維度降低一下,換一個視角看故障:

• 任何故障,一定是硬件如IaaS層,軟件如PaaS或SaaS的故障。 並且有個規律,硬件故障的現象,一定可以在軟件故障現象上有所體現。
• 故障一定隸屬於單機或是分布式係統之一,分布式故障包含單機故障。
• 對於單機或同機型的故障,以係統為視角,故障可能是當前進程內的故障,比如:如FullGC,CPU飆高; 進程外的故障,比如其他進程突然搶占了內存,導致當前係統異常等。
• 同時,還可能有一類故障,可能是人為失誤,或流程失當導致,這部分我們今天不做重點討論。

任何故障都可以套入到這個故障模型中。有了這個模型,我們就可以開始來設計模擬故障的演練係統。

所以在內部,我們起了一個代號叫做"大聖歸來"的項目,項目名叫做"故障演練",承載的產品叫做MonkeyKing。MonkeyKing是中國美猴王的意思,看重的是孫悟空高強的本領(火眼精金、七十二變)和極具反叛的精神來,希望用一種創新的思路來保證穩定性。

我們的係統實現,也是圍繞前文討論的故障模型來設計的:

• 在客戶機器部署OS層的故障插件,用來模擬硬件層的故障和單機進程外的故障。
• 對於應用進程內的故障,提供插拔式的故障插件,也可以用戶按照我們的故障API做自己的實現。
• 對於分布式故障,則通過服務端按照IP來控製故障的範圍。
• 對於一些因為各種原因無法觸及的應用,比如數據庫。我們提供了一個故障三方實現的標準,供故障服務接入。

通過上麵的方式,基本上就把技術型故障的模型就cover全了。

在去年的雙11中,故障演練的應用場景主要應用在圖中的幾個場景。 按照業務流量、壓測流量的峰值可以劃為4個象限。具體案例如下:

• 預案有效性:過去的預案測試的時候,線上沒有問題,所以就算測試結果符合預期,也有可能是有意外但是現象被掩藏了。
• 監控報警:報警的有無、提示消息是否準確、報警實效是5分鍾還是半小時、收報警的人是否轉崗、手機是否欠費等,都是可以check的點。
• 故障複現:故障的後續Action是否真的有效,完成質量如何,隻有真實重現和驗證,才能完成閉環。發生過的故障也應該時常拉出來練練,看是否有劣化趨勢。
• 架構容災測試:主備切換、負載均衡,流量調度等為了容災而存在的手段的時效和效果,容災手段本身健壯性如何。
• 參數調優:限流的策略調優、報警的閾值、超時值設置等。
• 故障模型訓練:有針對性的製造一些故障,給做故障定位的係統製造數據。
• 故障突襲、聯合演練:通過藍軍、紅軍的方式鍛煉隊伍,以戰養兵,提升DevOps能力。

故障演練宣言:把故障以場景化的方式沉澱,以可控成本在線上模擬故障,讓係統和工程師平時有更多實戰機會 ,加速係統、工具、流程、人員的進步。

故障演練的後續工作主要會關注在以下方向:演練常態化、故障標類化、演練智能化。用常態化的演練驅動穩定性進步,而不是大促前進行補習;豐富更多的故障場景,定義好最小故障場景和處理手段;基於架構和業務分析的智能化演練,沉澱行業故障演練解決方案。

原文鏈接

最後更新:2017-06-19 11:01:40

  上一篇:go  數加:從數據工程師到CDO的七次升職路
  下一篇:go  ntp時間同步返回“no server suitable for synchromization found”的排查