阿里專家樑笑:2018雙十一下單成功率99.9%!供應鏈服務平臺如何迎接大促
本篇文章來自於2018年12月22日舉辦的《阿里雲棲開發者沙龍—Java技術專場》,樑笑專家是該專場第一位演講的嘉賓,本篇文章是根據樑笑專家在《阿里雲棲開發者沙龍—Java技術專場》的演講視訊以及PPT整理而成。
摘要:2018年雙十一平穩度過,海量訂單、零點流量高峰,阿里是如何實現供應鏈99.9%的下單成功率?本次分享中,阿里2018年雙十一大促供應鏈服務保障平臺負責人向大家詳細闡述大促前4個月的全程經歷。面對大促第一步需要做什麼,流量峰值如何評估,效能優化從何處著手,一套有條不紊的供應鏈服務平臺迎接大促的解決方案至關重要。
演講嘉賓簡介:
樑笑,阿里新零售供應鏈平臺事業部,擅長 Java、Spring、OOP、分散式、架構設計,參與過供應鏈服務決策平臺、雙十一大促等專案,對業務開發、大促保障、架構設計等有所涉獵。
本次直播視訊精彩回顧,戳這裡!
PPT下載地址:https://yq.aliyun.com/download/3183
以下內容根據演講嘉賓視訊分享以及PPT整理而成。
本文圍繞雙十一大促歷程,從以下幾方面介紹供應鏈服務平臺如何迎接大促:
1. 概述
2. 梳理鏈路
3. 峰值評估
4. 容量評估
5. 效能優化
6. 依賴改造
7. 保障協同
8. 壓測檢驗
9. 專案協同
10. 監控治理
11. 戰前準備
12. 總結
一、概述
大家熟悉的供應鏈服務包括庫存控制、計劃調撥等,這裡介紹的供應鏈服務更偏向於交易側。例如在淘寶或天貓購買物品時,會有今日下單預計某日送達等物流提示,這種物流時效承諾即是由供應鏈服務平臺提供。再如,購買電冰箱、空調等大件需要預約配送時,需要選擇指定的配送商或者貨到付款、拆單合單等物流透出,都需要供應鏈服務平臺的支援。除了這些大家作為消費者可以直觀感受到的服務外,商家的商品入庫發貨等操作也都離不開供應鏈服務平臺。因為大促時物流服務需要實時透出,服務平臺是需迎接雙十一實時下單的高流量的,此外服務平臺還需要承接物流發貨的服務透出,例如發貨的倉庫、路線、發貨時效及服務等。因此,供應鏈服務平臺在阿里體系中扮演了一個上承交易、下接物流的腰部力量,主要包括物流服務、物流透出、商家訂購、容量管控等功能。物流服務及物流透出上述已提及,商家訂購包含倉訂購和快遞資源訂購,容量管控是指物流乾線的容量能力,例如從北京到上海,可以在當日送達的物流能力為一千單,超過一千單外的便無法達到這樣的物流時效訴求。至此,大家應大致瞭解了供應鏈服務平臺的概念。
供應鏈服務平臺保障的過程如下圖所示:
如何在業務容量峰值時保障系統,該採取哪些措施,這是一個不小的挑戰。首先,需要分析出哪些介面需要重點保障,哪些薄弱點或效能低下的鏈路需要重點評估。接下來,需要對這些進行優化操作。然後,對優化後的介面通過自測或壓測進行驗證。驗證過程中可能會發現,已有的問題解決了但是出現了新的問題,這就需要再次分析優化。這是個螺旋上升形的過程。上圖右側是保障過程的階段描述,會在接下來進行詳細闡釋。
二、梳理鏈路
如果給你一個系統,在你不瞭解的情況下,讓你在流量峰值下保障系統的穩定性,首先你需要明確要做的事情,清晰目標任務的範圍。因此,第一步就是梳理系統業務的鏈路,對系統有巨集觀全面的認識,這是保障大促穩定性的前提。但是,以服務平臺的現狀來說,有以下幾個通病:祖傳程式碼、上古應用、文件缺失、無人可問。阿里的服務平臺自2011年開始經歷過三次較大的升級改造,每次升級大部分核心功能會下架升級,但仍有某些小功能無法改造。這就造成在2018年的大促保障時還需要閱讀2011或2012年的程式碼,甚至某些應用都無法列印日誌。文件缺失、無人可問也使系統保障更加困難。
梳理鏈路可以分為以下四步進行:
1. 梳理對外介面。在日常開發中,主要的業務邏輯程式碼大約包含四五個對外介面,但是通常來說實際會比這要多。在對服務平臺的鏈路梳理中,新老三版系統包含大約80多個對外介面。但在實際工作中,只會涉及十個介面左右。可見,這些介面存在巨大的冗餘。某些介面可能已不再使用,或某些介面有使用者,但使用者並沒有意識到在呼叫該介面。因此,梳理對外介面就是梳理出介面是否在實際提供服務。
2. 移除無用介面。在剩下的70多個介面中,一定有無用的部分,移除這些介面也是移除了潛在的bug出現。這可以通過檢視呼叫者、分析流量或者諮詢使用者來進行移除。在這個階段,阿里的供應鏈服務系統大約下架了近40個廢介面,如此大幅縮小了需要保障的系統範圍。
3. 梳理剩餘介面。這個階段中將各介面按照重要性進行保障力度的劃分,例如某些介面是需要重點保障的,而某些介面無需重點保障,不應占用寶貴的機器資源、資料庫資源等,例如一些查詢功能的端頁面,在大促時出現問題也不會產生重大影響。
4. 確認強弱依賴。對劃分出的需要重點保障的介面需再次梳理出相互間的強弱依賴關係,這就需要理清系統的業務邏輯。例如在阿里的大促系統中,如果庫存出現問題,那麼緊接其後的訂單、配送等介面也都會混亂,這便是一個強依賴過程。因此,這裡應設定成如果庫存出現問題,下單隻能返回失敗。弱依賴過程則不同,例如根據歷史資料得知某消費者經常使用某一個自提站點,如果在大促中,自提站點的鏈路掛掉,分配的不是這個自提點,雖然這可能會導致消費者的愉悅感下降,但下單過程不會產生太大的問題。此外,還需對介面的呼叫量和呼叫比例進行統計梳理,例如呼叫一次A介面,可能會在下游呼叫一次或若干次B或C介面,通過這個比例可以根據A介面流量的增長幅度計算下游的介面流量。
如此梳理完成後便可以產出一份鏈路文件,大致掌握了需要重點保障的部分、可能的呼叫方、可能的消費者、消費的量級、涉及的資料庫、快取中介軟體、鏈路的強弱依賴等資訊,這是後續工作的綱領性檔案。
三、峰值評估
在有了這份綱領性檔案之後,則需要明確任務目標。對這樣實時下單的強依賴系統來說,最直觀的的目標是要支撐住雙十一零點的交易峰值。這就需要評估這個交易峰值是多少,畢竟每個系統被核心的交易系統呼叫的頻率並不相同。峰值可以根據交易下單量、業務預測和歷史經驗來進行評估。交易下單量相對來說確定性較高,因為這在系統內部可以通過限流解決。當下單量超出了系統的承受力,則直接返回下單失敗,讓消費者再次下單即可。因此每秒的最高下單量是相對確定的值。業務預測是指對每個行業線的下單量進行預測。即使知道每秒的下單總量,卻無法知道例如天貓超市或者某個行業線的細化下單量,那麼便收集該行業線下的店鋪資訊,再根據一些專業知識進行評估。這樣的業務預測值是缺少瞬值的,例如它可能可以預測出一天的單量,但無法預測0點那一秒的單量。因此,還是需要根據歷史經驗來彌補這個缺陷。例如根據前三年的大促流量分佈、雙十一前的三八大促九九大促流量分佈等資料,進行流量預估得到流量漏斗。甚至在大促前,對某些鏈路進行了改造變更等操作的,也需要在流量預估的過程中詳盡考慮。由上述可見,在這樣輸入有限的情況下,需要抽絲剝繭得出一份可能性較高的峰值評估。
這樣的峰值評估主要為兩方面,如下圖所示。一部分是介面峰值,這會用於指導保障整個系統。例如若下單量為十萬,那麼商品詳情介面大約會產生三十萬流量,渲染下單介面十二萬到十五萬,真正下單扣減約七到八萬,這些值會指導進行系統下單時的重點保障。另一部分是行業峰值。例如下單量為十萬時,快消品牌和美妝產品各自的單量為多少,這會直接顯示出系統各行業所需要的下單承受能力。
四、容量評估
確定了任務目標後,就需要評估現有的機器容量是否可以支撐預估的流量峰值。阿里的供應鏈服務平臺是一個單元化的應用,可以理解為一個跨城市跨機房的異地部署過程。每個單元(機房)有不同的流量承受能力,例如可以在華北設立機房承受30%流量,華南機房承受30%流量,華東機房承受40%流量。接著通過壓測等方法可以方便的得出單機效能,測試出健康情況下單機的QPS流量。例如,UNSZ(深圳單元)需要承擔6.52%的流量,結合單機效能預估需要的機器數量,根據比例得出預估QPS值。接下來需要考慮,現有的機器能滿足預估狀況嘛?是否有缺口?如果存在缺口,是可以通過優化還是申請預算解決呢?最短的木板(壓力最大的部分)是哪裡?因為各個機房的實際效能存在差異,這部分差異也需要考慮在內。根據最短木板確定限流保護值,重點保障最危險的單元。此外,在容量評估時,最好預留一定的buffer,保障可能超出的流量。
五、效能優化
基於已有的機器預算,和之前梳理出的介面鏈路,接下來需要一些手段優化效能來支援峰值流量。不僅包括對古老程式碼的優化,也需要對新產生的程式碼進行改進。下圖展示了供應鏈服務平臺的大促效能優化中採取的主要手段:
這些細節化手段這裡不再贅述,大家可以參考一些web技術文件即可瞭解,這裡重點為大家介紹如何梳理上述優化過程。沒有一個整體的方法論,貿然入手消耗的精力暫且不談,達到的效果可能也不盡人意。這些優化手段主要通過分析阿里的業務特點及雙十一的玩法特點得出。例如,若某一地區的倉配產能不高,無法實現物流時效承諾,那麼撤下物流時效承諾的同時,與其相關的鏈路也可以一同撤下,這便大大提升了這一塊的效能。因此,提升效能不只是通過記憶體調優等,也可以根據業務邏輯來調整。優化的各個步驟如下:
1. 減少流量。在客戶端或服務端遮蔽流量,降低不必要的呼叫,這樣的效能優化效果最為可觀。
2. 移除或降級IO。根據業務需求儘可能的下線無用的IO邏輯或者根據業務特點降級部分IO。
3. 減少IO呼叫。例如在貨品查詢IO中,可能會採用多個for迴圈來進行查詢,那麼便可以採用批量查詢來代替單個查詢。
4. 移除本地IO。移除和檢查沒用的日誌和濫用的日誌。某些debug程式碼在平時產生的流量不會引起大家注意,但是在全鏈路壓測驗證時就可能產生非常多流量以致執行緒卡住。
5. 使用快取。短時間內資料不變的情況下,進行快取,避免多餘的IO。這種方式在大促時效果尤為明顯。在電商行業,類似某個店鋪與貨品的繫結關係在大促時間內基本不會變化,這種不變的資料使用快取效果最佳。
6. 快取命中率。在平時快取可能設定失效時間為幾十分鐘,但是大促時可以禁止該類影響穩定性的操作,將失效時間設定為幾個小時甚至十幾小時。拉長快取失效時間,可以極大的提高快取命中率,平時的命中率大約在60%-70%左右,在大促時這個資料提升到了99.99%。此外,還需要充分預熱。
7. 快取吞吐。除了本地快取外,大家可能都會使用遠端快取,例如redis等。阿里巴巴使用tair快取,對其序列化方式進行了修改。java自帶的序列化方式效能較差,得到的序列化物件也位元組較大,因此將其改成了Hessian方式(沒有選擇kryo或protobuf是因為當時轉換成Hessian方式最為簡便)。同時精簡欄位,假設某個返回物件有十個欄位,但對外介面只需使用兩三個。大家知道,頻寬一定的情況下,單個數據量越大,同時能通行的資料就越少。流量峰值時,頻寬通常都會比較緊張,那麼便無需將剩下的廢欄位也存入快取。進行了上述改進,快取的吞吐有了很大程度的好轉。
8. 本地快取。儘量使用本地快取在tair前擋一層,避免網路IO。本地快取不可能存太多,但是在某些極限情況,例如卡券類或紅包等,當天呼叫極其頻繁並且不會變化,這樣的資料可以快取在堆外記憶體中。
9. 資料庫。在解決了資料IO的大部分問題後,便可以採取一些更細緻的優化手段。例如檢查慢的SQL,索引使用是否正確,有沒有離線拖庫任務,是否可以清理一些碎片等。
10. 原生代碼。去掉高頻率低效的原生代碼。但根據經驗,這種手段得到的優化效果有限。
因此,縱觀整個優化思路,減少IO和使用快取是優化效能的效果較為明顯的方法。
六、依賴改造
在效能優化後,大致不會在峰值時出現宕機的情況,但仍需要進行強弱依賴的改造,即強依賴改為弱依賴,弱依賴改為強依賴。強依賴是指如果對兄弟系統、資料庫或快取的調用出現問題,那麼流程直接中斷。弱依賴指即使這部分宕掉,可以直接設定超時或者熔斷,並不會影響流程的後續。強弱依賴的改造其實是一個兜底的過程。將某些錯誤的強依賴改為弱依賴,使其不會影響核心流程,防止雪崩。其次,將一些弱依賴改為強依賴。第一種是確定性的依賴更改。例如如果下單成功需要將扣減庫存數量,如果庫存數量沒有扣減成功,會導致後續各種問題,如果之前採用的措施是將這個異常catch住繼續後面的流程,那麼這裡就需要更改為丟擲異常阻斷流程。第二種是下游重依賴的資料。第三種是可能會造成資損的資料。強弱依賴更改實際上就是對業務負責和保障的過程。
七、保障協同
作為系統的負責人,做到上述效能優化等工作對本系統來說足夠了,但是其他兄弟系統的保障協同也是重要的一環。在阿里,每次中介軟體大規模要求升級時,大促也就近了。供應鏈服務平臺重度依賴的其他系統,例如商品中心、庫存中心、訂購中心和容量中心等也各自針對大促做了不同程度的優化。例如商品中心預熱手段發生了變化,重點流量做出分組操作,並專門留出了部分機器給服務平臺系統做流量分割。庫存中心升級了新模型,改進了快取等,那麼服務平臺系統也需要針對這部分進行相應的協同。和訂購中心的協同主要在預熱和防雪崩,假如宕掉時間過長,就避免呼叫資料庫,而去呼叫快取。容量中心之前只支援單個扣減, 現在可以支援批量扣減,或者修改了表結構。這些兄弟系統諸如此類的優化也從側面使得服務平臺更加健康。
八、壓測檢驗
完成優化和協同保障後,當然需要壓測檢驗。在雙十一期間總共經歷12次全鏈路壓測,因為無法再造一個全鏈路系統,所以只能使用真實系統壓測。為了不影響真實系統的執行和消費者的感觀,壓測通常在半夜進行。在壓測過程中,發現了不少問題,這裡舉出以下三個例子:
1. 本地執行緒池滿。jstack檢視執行緒堆疊時,發現很多執行緒卡在logback輸出日誌的地方。檢視原始碼後發現是使用log.error列印了一個很大的JSON物件,且每次呼叫都會列印,這就造成本地執行緒池立刻滿了。因為系統較老,依靠個人的程式碼review無法發現此類問題,這就需要壓測這種真實的流量手段來發現。
2. 超時請求。鷹眼(阿里全鏈路監控系統)發現有一個長達3s的請求,一般請求為毫秒級別,檢查後發現是該部分資料快取未預熱,查詢資料庫超時引起。因為該部分資料在大促時不會呼叫,因此在壓測時是可以提前將其撤下的。但在壓測時出現這個問題可能會影響到其他業務的穩定。
3. Jmap超時。阿里的服務平臺通過手工執行jmap命令觸發GC來釋放記憶體,發現在執行jmap時(會先下線對應服務),對應的機器仍然對外服務,並且大多超時。查看了對應的下線指令碼後發現,由於映象升級,導致Linux命令輸出與老指令碼預期不一致。這也影響了線上服務的穩定。
上述問題只有壓測驗證才會檢查出來,因此,壓測的意義不容置否。每一次壓測都是對上一輪優化結果的驗證,同時,每次壓測發現的問題,也是下一次優化的主要方向。
九、專案協同
服務平臺內部的工作同事便有10人左右,更要包括對外的例如中介軟體的部門、依賴和被依賴的兄弟系統部門。人員眾多導致各種協同問題的產生,這就需要一個協同機制。需要明確每個專案的負責人,有固定的聯絡方式。任務拆解要細緻,每個部分的任務交給指定的人解決。另外需要文件沉澱,得出的文件不僅是這次大促的回顧總結,也是下次大促的一個參考。2018年的大促能夠完成,也是依靠了之前的多次大促經驗文件。驗證考核也必不可少,驗證此次的優化是否達到了設定的目標。某些在測試時沒有顯現出的問題會在真實的流量下被發現,因此事後的驗證考核會幫助發現更潛在的bug。最後,風險識別,某些問題可能因為歷史原因無法修復,那麼這種問題要識別出來,和業務人員或產品人員共同找一個可以彌補的方法。例如可以將由於這個bug產生的問題訂單使用工具單獨丟擲,再行安排。這些都是作為一個專案PM需要注意的重點。當然,如果能有一個專案間供大家face to face探討各種問題是最好了。
十、監控治理
傳統意義上的監控治理有兩個訴求:看圖和告警。看圖主要關注各類曲線是否有波動是否穩定等,告警是在產生問題時可以通過簡訊、郵件等方式告知。除去傳統的系統監控指標,例如GC次數、記憶體使用率、QPS高低、系統反應時間,還需要業務監控,這需要通過日誌或離線採集進行統計,如此才能對系統和業務都有直觀的認識。當然,“會出錯的事總會出錯”,過程中難免會出現問題。如果出現問題,則需要及時統計產生影響的商家數量、單量、消費者數量,以便後續緊急處理,採取拉單、擴容或下線服務等手段防止過大損失,這便是消防處理。
十一、戰前準備
所有優化和監控措施完成後,大促開始前1-2天,按部就班執行各類計劃動作。首先是執行前置預案,例如下線了某些業務鏈路要執行觀察效果。其次是預熱,在大促前一天將一切準備就緒,準備迎接峰值流量。接著進行一致性檢查,單元化的核心應用涉及到成千的機器,可以通過計算MD5校驗值,來確保所有的機器上的zip、jar、war包等是一致的。然後資源檢查,對於大促當天的資料庫、機器、中介軟體、記憶體等資源做一個檢查,確保資源到位。清理資料庫,如壓測使用後廢棄的表可以刪除。最後,jmap釋放記憶體,將可能會觸發GC的記憶體全部釋放。
十二、總結
回顧整個大促過程,今年的供應鏈服務平臺比去年更加穩定,核心下單鏈路成功率接近99.9%,沒有發生限流等嚴重影響使用者體驗的情況。從8月開始思考雙十一的籌備工作,整個大促保障期間,涉及到眾多的系統、人員和業務,每個系統和業務分別由不同的團隊負責,需要做鏈路分析、模型分析、容量評估、目標評估,要協調和明確各節點間的職責劃分、要做各類優化、壓測、監控和反饋等等,持續了長達三四個月。
“這個過程是一次人與人、人與物件間的碰撞,精密的儀器產生完美的作品。”
原文連結
本文為雲棲社群原創內容,未經允許不得轉載。