餓了麼是如何做技術運營的

大雄45發表於2023-09-20
導讀 餓了麼平臺不僅做外賣,還有蜂鳥、早餐和未來餐廳,以及很多其他的一些平臺,正處在快速擴張階段。整個外賣的產品鏈條長,從使用者下單到最後配送到達,時間大概是30分鐘左右,對時效性的要求非常強。

從技術的角度來看,餓了麼遇到的最大挑戰是事故。本文將圍繞事故展開,分成兩部分內容:技術運營經歷與心得。第一部分經歷又分為三個階段:精細化分工、保穩定(容量和變更)和增效。第二部分心得,是作者對運維服務的理解。

一、技術運營經歷

技術運營的職責是盡最大的努力協同更多的人來達成保穩定的目標,可以劃分為兩個階段:運維保障、運維服務。現在,餓了麼處在運維服務的階段,技術運營團隊作為乙方,把開發出來的產品,開發測試後的服務,做維護,保障穩定、調優效能、提高資源的利用率。

在業務快速擴張階段,技術團隊需要做哪些事情呢?

首先,第一階段,精細化分工。

透過精細化分工促進並行提速,讓專業的人利用專業的知識、最有效的工作方式提高工作效率及程式碼吞吐量,建立溝通渠道加速決策、資訊流通保穩定。

精細化分工分為三部分內容:

第一部分是做資料庫拆分和程式碼解耦。技術工作集中在資料庫的拆分,先縱向拆分,不得已才做橫向拆分,為了更快地服務業務的擴張,又夾雜了一些對程式碼解耦的工作。

所謂 程式碼解耦,是把原來的程式碼系統想象成一個泥球,把它逐漸拆分成很多塊。現在是有十多個業務模組,每一模組裡面都有專門的團隊來維護,內部又會劃分域。

餓了麼是資料庫、程式碼拆分並行在做。然後,啟動了強制接入新發布系統和單例項、單運用,也就是物理拆分。

在整個的程式碼解耦和精細化分工的過程當中,他們碰到了很多問題,其中比較典型的兩類事故是:

  • 事故1:超時,後端服務慢,引發連鎖反應,導致前端服務雪崩。使用者的請求耗時依賴於 RPC 呼叫路徑上服務的響應時間。當其中某個節點變慢,整個叢集都不可用,一般救急措施是要按照呼叫鏈從前往後按順序停服務,然後在從後往前啟動服務。當這類問題發生的時候,如果沒有熔斷機制,前端的服務因依賴關係造成雪崩,而且服務不能自己恢復。加了熔斷機制之後,當後端問題節點重啟或是網路抖動恢復後,前端服務也會自己恢復。
  • 事故2:連續三天商戶需要不斷重試才能接單,這與Redis治理有關。當交換機發生 Bug 導致網路抖動,受影響最大的就是 Redis,在網路抖動期間積壓的請求會建立太多 Redis 連線,連線過多會導致 Redis 響應延遲從 1ms 飆升到 300ms。由於 Redis 請求慢導致服務的處理速度被拖慢,而外部請求仍在積壓,最後引起雪崩。剛開始出現故障的時候,因 Zabbix 的監控週期長,運維工程師監控不到。後來,他們用了三天的時間進行壓測復現,才排查出來故障點。事後,運維工程師打造了一種新的基礎設施監控工具,實現方式是每 10 秒鐘把 /proc 目錄下的所有指標收集起來,基本能做到 3 分鐘內定位問題。還有丟包的重傳也會嚴重影響 Redis 的效能,因為一個 HTTP 引擎到後端有可能產生幾十個甚至上百次的 Redis 請求,其中有一次被命中重試,對服務的影響都是致命的。

精細化分工的第二部分是組建水平團隊,例如大資料是水平團隊,業務線是豎向團隊,劃分之後,從整個業務的發展走勢圖上升曲線非常陡,可以推斷技術並沒有防礙業務的快速發展,也就是技術的吞吐量、新產品研發效率是健康的。

期間,運維工程師還做了幾件事,比如把監控分為 Metric、Log、Trace、基礎設施四個部分。組建 Noc 團隊,負責應急響應,當發現有問題的時候,及時把資訊透過 Oncall 通報給各成員。還有梳理各類掃除,接入釋出、 SOA,降級熔斷開發等。

大掃除

大掃除的概念是什麼呢?就是工程師對歷史的事故進行分析之後,大概做出技術總結,把經常犯的一些錯誤,列成一些可做的規程,給所在部門的骨幹進行宣傳。 具體內容包括:

  • SOA 的服務治理,這裡主要強調的是領域劃分,高內聚低耦合。
  • 對公共元件的治理。這裡的資料庫 Redis 由兩個專業的團隊組成,一個是 DA,一個是 DBA。DA 治理的主要方案是收集各個產業夥伴的資訊,規劃容量,治理開發的使用姿勢,把經驗固化到研發流程裡。
  • 業務指標的梳理,包括對 TPS 的概念設定(狀態輪轉後再根據返回狀態打點)、狀態的停滯時間和狀態的堆積深度,這個堆積深度主要是後端一些服務的狀態輪轉。
  • 對超時鏈的合理設定和重試機制。
  • 外部依賴及開關。為什麼強調外部依賴呢?外部依賴可以分為兩類,一類是跟其他公司的合作,例如呼叫其他公司的支付介面。還有一類依賴是團隊之間的依賴,這裡請不要相信任何人的服務,Bug 隨時都會發生。
  • 關鍵路徑。為什麼要設定關鍵路徑呢?一個是熔斷,一個是降級。當非關鍵路徑出現問題的時候,直接把它降掉就行了,不要影響關鍵路徑。另外一個好處是接下來做補償的時候,可以有針對性去做。
  • 日誌。團隊在日誌上發生的事故也很多,可以逐個透過案例進行宣講。
  • 正在實現中的制定盲演習目標。因為八九百個技術工程師之間的程式碼互動本身是一個複雜系統,業務又是一個非常長的業務鏈,關鍵路徑涉及的服務超過 100個,簡單的功能測試是可以的,但是容量大的時候,將很難定位他們之間存在的問題,比如 A 團隊和 B 團隊之間的程式碼耦合驗收。這時想到的解決方案就是盲演習。盲演習除了在業務方可以做驗收之外,還可以做基礎設施,包括 Redis 叢集、 MySQL 叢集和網路。曾經做過一個測試,把一個 Redis 例項上的包量,按照百分之一的丟包率計算,導致整個全站的業務都掉底。當時整個 Redis 叢集有12臺,有幾百個例項,其中一個例項有問題,就造成這麼大的影響。透過盲演習,技術正在尋求單個節點當機影響最小化的解決方案。
第二階段,保穩定期。頭號敵人是容量問題。

在業務快速擴張階段,影響系統穩定性最大的敵人是容量,類似溫水煮青蛙,或突然雪崩。因為不同語言判定容量的方式不同,餓了麼1000多個服務組成的複雜系統,業務場景快速變換,服務變更頻繁等等因素,導致容量問題困擾了近一年的時間。

最後採用的是 定期線上全鏈路壓測的方法,發動了一次百人戰役,歷時一個多月,整改了近 200 個隱患點,基本解決了容量問題。即便在低谷期的時候,也採用全聯路壓制。還可以配合技術在上線前的壓測一起來做,然後把這些資料統籌起來進行分析。

秒殺事故

在 517 秒殺大促準備階段,技術的運營思路是想用日常服務的叢集來對抗秒殺,活動前把整個的容量提高了兩倍多。但是當日訂單量飆漲,秒殺開始後的那幾秒鐘,瞬時併發請求達到平常的 50 倍。當流量洪峰到來的時候,洪峰直接把前端 Nginx 的網路擁塞了。

反思下來,出現問題的原因是秒殺場景的經驗少,對活動帶來洪峰資料的預估過低,URL 的限流未區分優先順序等等。改進措施是專門針對秒殺搭建了一套系統,主要做了分級保護、建立使用者端快取、泳道、雲叢集和競爭快取等。

第三階段,增效。透過工具、資源、架構改造,提高效率。
事故1:連續兩週蜂鳥配送出現各類事故

原因是訊息不斷的批次重試導致 RMQ 堆積,UDP 控制程式碼耗盡,熔斷判定使用姿勢不對。可以看出,新業務在快速交付過程中,程式碼質量、外部組建的使用姿勢是事故高危隱患點。

事故2:MySQL

SQL 慢查詢,從每週的 2 到 3 起,降低到近期很少出現。解決辦法是使用元件治理。元件治理首先是服務化自己的資源、容量。第二個是設限流,做降級。第三個主要是限制開發的一些姿勢。

這三點做完之後,接下來技術做了自動化相關的一些工作,主要是資訊、標準化和編排。再一個是前置指標KPI,就是當一些元件剛使用起來時,要做一些量化的考慮。把這幾條做到以後,技術基本上能避免出現大的故障問題。

對於使用姿勢的治理,對穩定的收益最大。這裡特別介紹幾個關鍵點:

  • 必須要有對元件精通的夥伴,看過原始碼,瞭解社群裡碰到的所有的坑,還要深入業務開發一線,瞭解業務場景,初步判定元件在業務中的使用場景。
  • 工程師進行知識傳遞,透過各種渠道把標準化、開發規範、叢集化、開發使用姿勢等知識點傳遞到位。
  • 儘快把經驗或紅線固化到資源申請、架構評審等流程、工具裡。
事故3:RMQ

在餓了麼,RMQ 的使用場景非常多,有 Python,也有 Java。2016年年初的時候,工程師雖然做了一個技術、配置的梳理,還是留有很多的場景是沒有想到的,主要涉及的問題有如下幾個:

  • 分割槽,就是技術在做割接的時候,核心交換是升級換裝置。當裝置網路割接完了,雖然在 RMQ 叢集裡面的配置是可以自恢復的,但是仍然還有很多叢集沒有做到自恢復。所以,技術特意預留了一個冷備 RMQ 叢集,把現網所有的配置都部署到那一個冷備叢集裡面去。線上 20 多個 RMQ 叢集中,如有一個宕掉的時候,可以及時切過來。
  • 佇列堵塞。主要是追查消費能力,因為業務飆升,消費能力不夠,極容易導致佇列堵塞。
  • 使用場景。舉例來說,在傳送、接收訊息的時候,如果每發一個訊息,每收一個訊息,都重建一次連結或者都重建 Queue。這種重建會導致 RMQ 內部的一個Event機制。當請求增長到一定程度的時候,就會直接影響 RMQ 的吞吐量,RMQ 的容量會掉到是原來的十分之一。

老大難:故障定位、恢復效率

故障定位慢的最主要原因是餓了麼整個系統的資訊量太大,當一個問題出現的時候,主導這個事故定位的工程師拿到的資訊非常多,比如拿到三個資訊,他很難決定到底是什麼故障,需要如何檢測出來。

當前的做法是進行碎片化、地毯式的大掃蕩來排障。什麼是地毯式的大掃蕩呢?就是把足夠多的資訊先拿到,進行分工,要求涉及的每個工程師都來檢視。內容涉及到外賣、商戶、支付和物流,然後還有基礎業務和網路監控,外網的一些流量,還有伺服器的一些負擔等等。

這時,技術工程師的有序自證就變得非常重要,當前能做到的是每一個人能看到當前負責的服務是不是有問題。還需要做的就是提供工具,比如交換機的丟包、伺服器的丟包。透過一些工具,讓技術工程師及時發現問題,但是這個過程是需要時間的。

另外一個是在自證的時候,一定要仔細地檢查。作為團隊中的一個成員,每一個技術工程師負責相應的板塊,但一旦因為個人疏忽或是自檢不足造成一些失誤,要自己“刷鍋”。故障定位後,提升恢復效率解決問題才是關鍵。

還有,應急演習很重要。應急演習直接關係到系統恢復的效率,當一個叢集出問題的時候,技術能不能快速的恢復。

二、運營心得

本次分享大部分圍繞事故來講。每一次事故的出現都不是偶然的,很多問題是可以透過正確的使用姿勢、提前做容量預估、灰度等方法規避的。如果說技術只是就事論事把這一件事情解決的話,事故往往在另外一個時間點還會出現。這就要求工程師以思考的方式去做事,比如做事故覆盤、事故報導稽核,還有驗收小組等。然後,透過在各個階段,多次把一個事故涉及的關鍵點提出來,不斷地進行總結並制定可行的操作規範。問題的解決往往需要思維模式的轉變,需要夥伴們多想想怎麼從日常重要緊急的事務裡抽離出時間思考。還有要敢於折騰。折騰是什麼概念呢?就是要不斷的演習、搗亂,工程師對於維護的系統,自己要非常的熟悉,這樣在定位和解決故障的時候,就會非常精準。最後一個是燈下黑的問題,特別是基礎設施這塊。這在當時讓人很頭疼,查一個問題在基礎設施上花費的時間是十多分鐘到一個小時。後來有一個小夥伴改變思路,做出了一套系統,幫助團隊非常好地解決了這個大問題。所以敢於思考,勤於嘗試是餓了麼技術團隊非常重要的一個心得。

原文來自: https://www.linuxprobe.com/eleme-devops.html


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2980436/,如需轉載,請註明出處,否則將追究法律責任。

相關文章