天天看點

餓了麼傳遞中心語言棧轉型總結

前言:

本文介紹了餓了麼傳遞中心由python語言棧轉換到java語言棧大緻過程,一來是對前段時間的工作做下總結,另外也是想通過此次總結為其他應用服務轉型提供些借鑒。寫的不好,歡迎闆磚。

背景

餓了麼并入阿裡集團,為了能高效與集團内部系統協同對接,同時友善利用集團優勢技術資源,更好的融入阿裡集團技術生态圈,餓了麼交易中台在上半年啟動了交易領域的四大應用語言棧轉型項目,為阿裡集團本地生活服務平台打好技術平台基礎做準備。另外,随着業務量的激增,餓了麼平台支援的品類不僅僅是最初的外賣單品,整個交易中台也需要一次相對大的重構來快速應對複雜多變的業務需求。而本文中的傳遞中心即是餓了麼交易領域四大應用之一。

準備

在開展相關工作之前,首先必須得清楚我們是要将一個系統從什麼樣變成什麼樣,新的系統相較老的系統在哪些方面做的更好,同時必須保證新老系統的無縫切換,做到業務無感不影響交易系統的穩定性。

系統價值

外賣訂單的業務特點是重交易,c端使用者從下單選餐到騎手完成餐品傳遞過程,目前大部分都能在半小時左右完成,對即時配送實時性要求較高。整個訂單交易過程大緻劃分為:1.添加購物車确認訂單,2.訂單生成及訂單支付,3.接單及訂單傳遞,4.可能的售後退單。而要更好的服務使用者,對四個系統穩定的協同能力提出很高的要求。

餓了麼傳遞中心語言棧轉型總結

如前文所述,我們知道履約環節對交易訂單的價值是什麼,即是将外賣訂單對應的餐品傳遞到使用者手中,技術層面上來講,傳遞對交易訂單屏蔽了一切其他履約細節,使訂單更專注訂單領域業務。

核心分析

接下來,我們再進一步詳細的剖析下轉型前傳遞系統所承載的功能。

餓了麼傳遞中心語言棧轉型總結

如上圖所示,原傳遞履約領域中包含了三個較大闆塊:

  • 1.訂單對接運力線子產品
  • 2.商戶訂單資訊子產品
  • 3.部分金額計算子產品

可以看出原系統所承載功能并非真正聚焦在訂單傳遞過程。怎麼辦?轉型重構是個契機。商戶訂單回歸到訂單,金額計算下沉至結算,這兩部分的相關轉型重構這裡不再贅述,相關部分也已由兄弟團隊完成。其實到這裡傳遞履約應該關注的已經很明顯:把外賣訂單給運力線,使其完成傳遞履約。

基于剛才提取後的傳遞履約核心領域,我們對主要的場景用例進行了詳細的梳理。如下圖所示,可以看到:

  • 參與傳遞過程的主要角色有四個:
    • 1.商戶
    • 2.訂單
    • 3.履約運力線
    • 4.使用者
  • 傳遞提供的主要支撐能力有:
    • 1.乎單傳遞能力
    • 2.運單狀态同步能力
    • 3.運單資訊透出能力
    • 4.履約方式切換能力
    • 5.運單狀态廣播觸達下遊能力等。
  • 部分運單取消或異常管理。

系統核心用例分析如下圖所示:

餓了麼傳遞中心語言棧轉型總結

更詳細的系統用例梳理或系統上下遊互動時序這裡不再一一列舉,需要說明一點,當大流量系統轉型遇到重構,要想走的夠遠夠穩,前期的仔細調研工作及功能對齊過程非常重要。特别是生産環境已經跑了好幾年核心功能系統,實際業務情況錯綜複雜。例如要轉型重構系統接口能力,接口含義,場景必須都要詳細掌握。

設計

至此,我們的目标已經很明确:1.語言棧轉型,2.過程中要将不屬于傳遞的東西從原系統中分離出去,使得傳遞領域更幹淨。結合傳遞未來可能的發展方向,其中傳遞能力可複用的,履約運力線可擴充的。這對整個傳遞可快速疊代對接提出了更高要求。另外,我們也在領域模組化設計思想指導下做了些實踐嘗試,于是有了以下架構結構。

系統設計

轉型是把python方言轉換到java方言,傳遞系統核心能力不會有變化。能力的複用是通過接口次元的抽象聚合産生,履約運力線能力可擴充通過利用業務架構擴充點特性滿足。拆分後的業務架構應如下圖所示:

餓了麼傳遞中心語言棧轉型總結

系統架構

業務架構結合目前餓場基礎元件支援我們不難給出以下系統内部子產品劃分:

餓了麼傳遞中心語言棧轉型總結

簡單對各組成子產品做簡要說明:

  • api:處于業務架構中上遊系統接入層,對外暴漏契約屏蔽細節,對内定義系統能力。
  • starter:啟動項目
  • service:rpc服務暴漏
  • domain:核心業務能力實作,聚合層
  • infra:基礎資料支撐能力層
  • extension:履約能力擴充層
  • tester:單元測試包

到此,我們可以按照設計與既定的計劃撸代碼了。

嗯,代碼撸完了測完了,從調研到開發完成曆時兩個半月,代碼倉庫總行數約4.7w行,送出1000次左右,完成63個接口+16個消息消費入口轉型遷移,共計測出117+bug,期間有喜有憂,奮戰兩點多是常态。職業生涯中濃重的一筆。此時尤記起與超哥@鄒超周末代理聯調于北14樓小黑屋之畔,和明龍@張明龍并肩作戰對接服務接口,還有曉波@俞曉波淩晨一同壓測觀察總結問題第二天分析回報提升優化,當然還有傑哥@湯良傑的用例設計全面不失細節、對bug常常究其根本,對代碼review邏輯核對一絲不苟明察秋毫。凡此種種,曆曆在目。一起走來,真心感謝。

                    ------  不由自主的感概下  ≧◇≦

平穩過渡

代碼撸完測完才做好轉型工作的第一步,将流量穩步平滑過渡到新的服務中,做到上下遊無感是轉型過程中面臨的另一大挑戰。

說到這裡,要達到系統的語言轉型前後的平穩過渡其實是在說轉型前後對我們系統的使用者SLA(Service Level Agreement)提供一緻性的保證。這裡先簡單聊聊系統服務的SLA。

服務可用性級别 服務正常運作時間百分比 年當機時間 日當機時間
1 90% 36.5day 2.4 hour
2 99% 3.65day 14 min
3 99.9% 8.76day 86sec
4 99.99% 52.6min 8.6sec
5 99.999% 5.25min 0.86sec
6 99.9999% 31.5sec 8.6msec

上表格是業界服務高可用的幾個級别的衡量标準,例如:服務可用性是3個9時,全年當機時長約為8.76天的統計機率。另外,我們需要明确的是不同的系統,不同的場景以及不同的使用者規模對系統可用性要求是不一樣的。如:某些業務的支付鍊路場景可能tps不是很高,但是作為交易的核型鍊路必須得保證進階别的可用性。

怎麼保證或者提升系統服務的SLA呢?在明确我們目标後,接下來就是拆解目标量化目标。

you cant measure it,you cant fix it and improve it.

一般來說,影響系統服務可用性有兩個重要因子:

  • MTBF:Mean Time Between Failures,系統服務平均故障時間間隔。
  • MTTR:Mean Time To Recover,系統服務平均故障恢複時間時長。

是以大緻可以簡單歸納為這樣的一個函數關系:

餓了麼傳遞中心語言棧轉型總結

可能無法給到一個精确的數學描述,但是可以做定性的分析:恢複時長因子與系統可用度成正相關,故障間隔因子與系統可用度成逆相關。也即:_問題出現時恢複時長要盡可能的短,盡可能降低故障頻率以增大故障間隔。

基于以上理論,我們在做系統平穩過渡無縫切換時,無論資源使用,業務内部邏輯實作及灰階方案,我們都需要着眼于這兩個方面。接下來我們将從這兩個點出發分析轉型過程存在的挑戰及我們的應對方式。

快速響應,降低恢複時長

要做到恢複時長盡可能的短,首先我們需要保證在前期出現問題時流量切換過程中流量規模盡可能的小,即需要一個相對的合理的灰階梯度方案。其次當問題出現後我門需要能立即回切到原系統,不至于反應過慢導緻大量增量問題産生,即需要一個響應高效的開關復原方案。由于轉型過程中涉及的接口和消息消費入口較多,另外我們還需要考慮到後期問題排障和快速定位的可能耗時。

  • 針對灰階梯度合理制定,根據業務特征,開始階段我們選擇了較冷門城市(訂單量較低)進行了各個運力标品業務的邏輯驗證。标品驗證完後說明我們新遷移實作的邏輯和原系統具有一緻性。随後我們拉取了目前訂單城市分布,根據城市訂單分布占比制定灰階梯度,由小到大逐漸增加。
  • 針對回切需要響應高效,我們應該有一個總的開關可以控制流量,回切應該是一鍵控制的。
  • 針對排障快速定位,灰階單生命周期内的操作能在單應用内自閉合,不至于排障時還需要确認灰階單某個狀态到底走的原系統服務還是新系統服務。另外我們還希望,寫操作灰階和查詢灰階能單獨隔離開,等寫資料完全一緻的情況下我們再開啟新資料新接口查的灰階,将風險控制到最低。

是以我們采用了如下的老系統服務代理方案:

餓了麼傳遞中心語言棧轉型總結

如上圖所示,訂單系統建立訂單時根據既定的灰階計劃讀取配置給訂單打标,灰階計劃分為前期分标品,門店次元驗證,後期按城市訂單分布次元配置。若新系統服務出現問題可一鍵切掉灰階流量,止血增量問題。接着,原傳遞老服務識别标記做代理轉發,訂單不存在遷移标記則原流程操作處理,否則轉發到新傳遞中心新服務操作處理,相應的消息監聽處理同樣也是參照訂單标記,這樣保證了同一個訂單的傳遞過程能在一個應用中完成,有利于後期處理流量上來後的快速問題定位。

另外,我們的接口灰階過程是寫與查分離的,整個遷移過程大緻分為三個階段,如下圖所示:

餓了麼傳遞中心語言棧轉型總結
  • 第一階段 灰階寫階段,灰階政策:餐廳次元,城市次元小範圍灰階,讀流量以老服務為準,問題出現及時切掉灰階寫流量,邏輯復原至老服務。
  • 第二階段 灰階查詢階段,灰階标記流量以新服務為準,非灰階标記以老服務透出為準,灰階政策:各個查詢接口按照百分比逐漸增加灰階占比。
  • 第三階段 遷移階段,完成讀寫灰階,原系統老服務隻是代理的一層皮,接下來就是上遊系統遷移到新服務,去掉對原原系統服務的依賴,遷移完成。

最大努力降低故障風險

平均故障間隔是一個後驗時長資料,要做到間隔時長盡可能的長,日常裡就需做好釋出控制,風險巡檢及持續監控等工作。

1.釋出控制

轉型期間新系統服務必須遵循釋出sop,餓場釋出sop已經形成共識,我們隻需嚴格遵守,這裡不再贅述。

2.風險巡檢
  • 系統邏輯核對,多人多次code review。
  • 變更釋出前主幹場景自動化用例全通過。
  • 周期性壓測。
3.多層次持續監控
  • 部署機器,緩存叢集,消息隊列,資料庫表等基礎資源的基準監控。
  • 業務曲線成功率,日同比,周同比,曲線波動比,及主要接口入口流量到下遊出口流量轉換率監控,業務系統成熟後還應對各個服務響應時間名額做監控等。
  • 系統中很多情況下重試都是以異常中斷為依據,這必然會對系統異常點帶來較大的噪音。為此我們還需要細化各個中斷異常的打點,排除不必要的幹擾。

一緻性問題

轉型過程中我們實際上同時做了資料模型優化遷移,對外為了保證新老系統行為屬性的一緻性,我們還面臨以下幾個挑戰:

  • 灰階資料需要雙寫新老傳遞系統庫表,如何保證雙側底層資料的一緻性?
  • 底層資料一緻不等于對外服務接口資料透出一緻,雙側服務應用層面怎麼保證資料的一緻性?
  • 訂單阿波羅履約線和傳遞的上下遊資料資料最終一緻性怎麼保證怎麼驗證?

一緻性的保證,别無他法,隻能通過比對來做。但在做比對的時候我們還需要考慮到比對本身隻是我們驗證遷移系統正确性及穩定性的一部分屬旁路,并非生産環境的必須功能。即我們得考慮這部分功能對現有系統可能造成的壓力。這部分壓力應該是随着系統驗證完畢是可開關的,壓力大小應随系統的表現可随時調節。不至于因為驗證拖垮了生産應用。是以我們對比對的基本要求是:能一鍵開關,可監控可追溯。除了這些共性,具體還應做到以下幾點:

  • 針對底層資料比對:
    • 比對應是準實時的,如隻比對30分鐘前的資料。
    • 比對資料是基于時間可分段采樣的,如隻比對10分鐘以内産生的資料。
    • 為了友善控制,根據情況以上政策又可以是及時調節的。即準實時偏移量可調節,分段采樣視窗大小可調節。

具體實施方案如下:

餓了麼傳遞中心語言棧轉型總結
  • 針對應用層資料比對:
    • 代理層接收請求後,比對應是異步的,不影響接口響應耗時。
    • 比對粒度要小,應細化到接口。
    • 識别灰階資料,隻做有效比對。
餓了麼傳遞中心語言棧轉型總結

無論資料層面還是接口層面出現比對不一緻,應立刻去分析是什麼原因導緻不一緻。解決根因逐漸降噪,隻至比對差異在我們認為可接受的範圍内。

  • 針對上下遊資料最終一緻性:
    • 全量資料核對
    • 主幹鍊路最終一緻性核對

經過資料準實時比對,接口實時異步比對,其實基本可以确認新老系統能力行為屬性對等性。然而穩定大于一切,要百分百确定還需要t+1資料核驗。即從全局資料角度看新老系統轉換的影響。這裡以主幹鍊路呼單多日成功率為例做簡要說明。如下圖所示,多日乎單成功率基本在99.9977%左右,可以認為新老系統代理切換傳遞成功率基本表現穩定。

餓了麼傳遞中心語言棧轉型總結

未來

截止此文攥寫時間,餓了麼傳遞中心已經完成了整個系統的語言轉換,流量也已經100%切換代理到新系統,處于流量切換的第三階段。結合日常系統維護與需求疊代實踐,我們仍需要再以下幾個方面進行更深入的思考:

  • 轉型過程中為了在易測,可核對同時與python的“魔法”姿勢鬥争中找平衡,部分邏輯是"純翻譯"的,後期維護過程很痛苦,是以我們需要幾次不小的重構來達到代碼層面的和諧。
  • 不斷監控降噪,持續細化監控粒度,監控是服務穩定基石。
  • 傳遞中心資料大盤建設,從資料層面量化觀測我們的傳遞品質。資料驅動,數字營運從資料化思維優化我們的流程,提高我們的服務。

方法論沉澱

凡此以上,服務系統轉型遷移歸結于開發者了解與認知,項目的穩定實施歸結于開發者套路方法運用。可以簡單進一步提煉為以下方法論:

  • 詳細調研,客觀問題及滿足業務的系統是複雜的,詳細調研做好準備是必須的。
  • 持續監控,感覺系統的品質是服務品質度量的第一步,不斷持續的監控才能走的更穩。
  • 穩步過渡,網際網路系統服務高可用穩定不容商量。
  • 問題發現根因解決,小的問題可能隐藏大的bug,認真對待究其根本,複盤->總結->提升。
  • 歸納總結業務再認知。
    餓了麼傳遞中心語言棧轉型總結

關于認知提升的幾個小點:

  • 對于每一位工程師,開發高并發大流量系統是挑戰也是機遇。時刻保持進取學習心态,增強自身軟素質。
  • 分布式情況下,承認系統并非絕對100%可靠,每一個環節都要考慮“失敗”了怎麼辦,不同的場景我們需要在AP和CP之間作出抉擇。如雙鍊路調用保證可靠,異步重試保證順序最終一緻等。
  • 出了問題快速恢複是個永恒的話題,沒有“怎麼樣“最快隻有”這樣”更快。精準定位立即恢複,如何将這個過程耗時降到更低值得深入思考。

作者資訊:李傑,花名項庭,目前主要負責餓了麼傳遞領域系統。