數人云「告別人肉運維」上海 Meetup 的實錄第一彈來啦!本次分享的嘉賓是餓了麼技術運營部資深專家王偉珣。從源頭出發,餓了麼基於架構和平臺設計的"design for failure"實踐,作到自動化運營和運維實踐,防止人爲操做失誤。前端
王偉珣 / 餓了麼技術運營部資深專家redis
曾是 EMC Pivotal 亞太區 CTO office 資深架構師,成功在中國和亞太各個等行業推廣使用了新一代分佈式數據庫和 Docker 。中國移動遊戲基地和視頻基地平臺技術負責人。擁有五項技術發明專利,國內第一代互聯網建設者, GNU/Linux 開源運動和信息安全國內最先的推廣者。數據庫
你們好!我加入餓了麼大半年了,今天分享一下餓了麼在技術架構運營方面的一些實踐經驗,基於這個架構餓了麼已經作了一兩年的時間。緩存
首先,餓了麼很是強調 design for failure 。餓了麼如今的 IT 架構通過多年的發展,已經變得至關複雜了。在這個 IT 架構裏面,要追求三個 9 、四個 9 ,甚至六個 9 。在這種複雜的軟硬件架構狀況下, 15 分鐘以內人肉去判斷故障在哪裏是很難的,更況且還面臨着業務的中斷帶來各類緣由。前有 Gitlab 這個事情人肉操做的出錯,一個系統可能你要運行五年、十年甚至更長,誰都不敢擔保再怎麼樣細心都不出錯。這麼多年,各類各樣的軟硬件 bug 、生產過程當中的質量問題都會碰到,因此純粹是靠各類各樣對人的一些約束或者 SOP ,實際上不能完全解決問題。安全
個人理念是採用負載分擔多活,以分佈式架構去作到 design for failure 。互聯網多數會考慮負載分擔多活,但實際上在廣義的 IT 行業裏面好比說芯片設計以及航空航天,飛機和衛星上的軟硬件設計,自己也有這樣的一些要求。你們若是從企業級去學習、被 IOE 洗腦的話,那麼他們提這個比較少。由於要作到負載分擔多活,就不會去買 IOE 那種大設備了。服務器
作到負載分擔多活,能夠獲得的一個收益是自動容錯,不管是硬件的質量問題,仍是外界環境,好比光纜掛斷、掉電、軟硬件的 bug ,它都可以自動斷定而且自動容錯切換。好比作衛星的軟件,衛星發射上天,低溫 110 度,高溫 180 度,上天之後要工做 15 年,不能修、不能換,可想而知這個要求很高的。按照最高要求去對比,企業級的不少要求已經低得多了。若是作一個軟硬件要求 15 年不能修、不能換,一直工做下去,並且環境那麼惡劣,發射的時候加速度 10 到 100 個 G ,它要在實驗室裏面抗住 100 個 G 振動,才能抵得住發射過程當中的挑戰,因此這種負載分擔多活相比航空航天軟件是一個不算高的要求。微信
在負載分擔多活的架構上,首先要解決機房內的架構,這個架構按照業內的術語是叫 SOA 分佈式架構,在這個圖上看上去有點複雜,簡單來說就是每一個模塊其實是多個的,每一個單元它是多個負載分擔,並且可以自動地擴展和容錯切換。這個架構在一些友商,例如 Netflex 開源的部件裏也有相似的設計理念, Google SRE 的書裏面也提到了他們的作法,餓了麼跟 Google 、以及你們所知的騰訊阿里也實現了相似的架構。網絡
先介紹一下它工做的結構。核心是 SOAGateway 去負責後面全部服務部件互相之間的負載分擔、調度、徵錯、容錯等等。前端有一個 HTTPizza 的環節,在它外圍的外層有一個 APIRouter ,它是負責廣域的負載均衡,會根據一些後臺的狀況,基於就近規則或者是出事故的時候切換規則,把請求業務指派到某一個機房去。進到這個機房之後會有一個轉換的環節,把 HTTP 協議轉成高性能的二進制的 Thrift 協議,而後經過 SOAGateway ,根據調用的服務轉到不一樣的服務單元。全部的服務單元有一個公共的註冊和健康檢查的環節,還有 Service 的註冊環節。在下面有幾個公共的數據服務部分,好比 DBA 數據庫部分,還有很是大量的 Redis Cluster 部分,以及一些異步的服務調用環節,用 mq ,餓了麼有自研的 maxmq ,也有在用老的 Redis mq 。架構
在整個分佈式架構裏面核心是 SOAGateway ,如今也有稱之爲微服務的中間件,這跟已經開源了很長期的像 Spring 、 JBoss 這些中間件是不同的。 Netflex 開源了一個,有點像 v1.5 的版本,可是它還依賴 Spring ,沒有完全作到徹底的語言中立化和徹底的鬆耦合。負載均衡
整個分佈式系統如今有 1100 多個服務部件,有 7000 多臺服務器,全部服務的啓動、配置管理,啓動的時候會自動登記,服務發現,健康檢查,以及斷路器、智能路由、控制總線等等都在這個中間件去作。核心是一個分佈式服務架構,模塊之間爲了作到高性能和語言中立是用了 Thrift RPC 協議,這樣就使得每個模塊的開發者不用關心具體的開發語言了。內部有 PHP 、 Pyhton 、 Go 還有 Java 來作不一樣的部件、不一樣的模塊。
design for failure 最核心的就是這個中間件,具備服務高可用性的功能,可以作到自動負載均衡、自動的熔斷與容錯。熔斷是指某一個部件若是響應時間或者是鏈接數超過閥值的狀況下,它會對某些請求限流,或者在有新請求的時候會把非關鍵業務環節臨時的自動關閉掉熔斷。容錯是好比這個系統部署了 80 個或者 100 個服務器,部署了那麼多份,但其中某一個服務器因爲網絡或者硬件的各類故障,由於在服務註冊環節是有一個心跳檢查的,包括服務本身也有一個心跳上報的機制,一旦發現某一個服務器有問題就會自動把它排除,因此對攻擊、故障、網絡的擁塞以及服務的過載可以自動的應對、自動的限流切換,達到服務的高可用性。
Thrift 協議是一個高性能的語言中立的協議,已經支持了各類開發語言。固然,這個分佈式服務架構涉及的系統很是龐大,前面也提到有 7000 多臺服務器在生產,因此配套了一個 Web 管理界面。另外,餓了麼已經可以作到程序的分佈式分發,如今在作 Docker 化的軟件分發,有關功能正在開發中。
design for failure 是一個很重要的架構設計理念,在這個設計過程當中餓了麼也有一些技術的實踐。 SOA 架構或者另一個名詞叫微服務化,主要是對這個服務進行有效的拆分,使得部署可以方便化,不會各個環節互相的牽扯。在整個治理服務架構的設計中,咱們也參考業內一些成功經驗,業務模塊基本上是先按照業務流程的 BU 再劃分,根據業務來進行劃分大的模塊,那麼由一系列的服務來組成某個 BU 的業務系統,每個服務是能夠單獨部署的,並且全部的這些服務版本是根據業務週期去肯定而不是說根據某一個項目。
在新一代的 SOA 架構裏,強調的是強內聚弱耦合,前面提到的這些服務功能和流程邏輯是每個服務組件本身承擔的,中央的 SOAGateway 只負責派發以及服務尋址等。在初次調用的時候 SOAGateway 會經過狀態查詢和服務註冊,幫你指派到哪個服務單元,服務單元之間是 P2P 直連的。在某一些業務模塊流程,它也經過 SOAGateway 集羣進行派發調度。前面所說的整個 1000 多個模塊的系統,它的發佈、部署是由軟件開發的各個小團隊作 DevOps ,即整個發佈系統,他們能夠本身去操做。在發佈過程當中,分佈式架構裏的灰度發佈、隨時回滾,發佈過程也就是生產過程當中遇到各類差錯跟切換的容錯也是整個架構必備的一個部分。
餓了麼在自研 SOAGateway 的同時,也自研了一個 Redis Cluster 的軟件 Corvus ,現已開源。 Corvus 要比 Redis Cluster 官方的版本稍微早一點出來,在 Redis Cluster 架構的設計理念在部件自己也是實現了一樣的分佈式多活負載分擔的架構,這裏着重介紹一下它在數據 Cache 的層面作到數據的分片,主從同步,在磁盤作一個 AOF 的緩存等等,這樣的結構來保證高性能的同時高可靠,作到多活主從,它的 slot 節點也是能夠讀的。
前面介紹的是單機房內的分佈式多活的架構實現。另外,餓了麼也在作多活的平臺架構。你們每天在用的微信、 QQ 以及 3G 、 4G 網絡,都是所有 IP 化的,也是由很是龐大的多機房分佈式系統來爲你們服務。不管打開微信也好,仍是打開餓了麼也好,客戶端其實會自動上報本身的一些 ID 狀態,後來會有一個 Gateway ,各家可能叫法不一樣,會根據用戶的各類屬性狀態把用戶派發到某一個服務的單位,好比餓了麼如今初步分紅南北兩部分,北方用戶在打開客戶端連入系統的時候,沒有感知地就被派發到了北京的數據中心。若是南方的話,那麼就會被自動派發到了南方的數據中心。
固然,南方和北方之間是做爲互備雙活的,假設北京的系統掛了,最外層的 API Router 會知道,它就會把全部請求所有給派發到南方去。由於南方、北方其實都有全部用戶的數據,即持久化層的數據是全量的,只是應用層服務模塊的邏輯是分別部署。裏面的數據複製是多活的核心環節,以後我會細講如何作到雙向的複製。南北是雙活,同時又是爲互備。餓了麼作到了多活之後,災備通常也達到了一樣的要求,本質上是互爲災備、互爲備份的。
IOE 經常講的「兩地三中心」,那個是賣盒子的作法,不是真正考慮到 design for failure 的作法。在多活的這個架構裏有一個基礎,必須對用戶在業務入口邏輯的時候就立刻進行 sharding ,不是傳統數據庫 sharding ,數據庫 sharding 其實是爲了負載分擔的而不是爲了作多活的。因此在業務入口的這個環節基於業務邏輯作 sharding 之後,後面分紅兩個雙活仍是分多活本質上沒有區別了。餓了麼的商家是按地域分佈的,在上海作的消費請求與在北京作固然是不一樣的,因此業務的邏輯就是自然分割、自然分佈了。
互聯網公司好比微信,也有相似的邏輯。用戶連上去的時候會就進到某一個經常使用服務機房,若是用戶從上海到成都,用戶短時間內接入成都之後,它會幫你轉到上海,但若是在成都多待了多少天,有一個後臺邏輯,會把該用戶持久化數據的歸屬主服務點切入到成都。如今 3G 、 4G 的通信網絡全 IP 化了,也是有相似的結構,開戶的所在地好比上海就在上海,可是到北京去之後,北京的訪問登記中心會自動跟上海 HLR 鏈接得到用戶的屬性和註冊,才使得用戶在北京可以通話,通信網絡自然也是一個多活的。
在餓了麼架構裏面由於涉及到比較多的商戶邏輯和用戶邏輯,持久化數據量比較大,核心是數據庫裏面有一個 DRC 的環節,承擔數據複製的工做。這個工做有兩個用途,一方面用戶換地方的時候,好比從上海到北京,那麼用戶開機是連到北京的,該信息在北京也要有,因此持久化數據是全量的。前面也提到雙活即災備,起到災備的做用。在數據複製的技術上面,是基於數據庫軟件層面來作的,也具備靈活性和能夠作多路分發的好處,這裏只是最簡單的廣域的雙向複製功能。複製過程當中還會去通知遠端 Redis Cache 的刷新,會去通知一些 mq 的狀態變動,都是 N 對 N 的一個多向的功能。
最後總結一下個人理念,真正要作到整個系統讓你們晚上不會老是接到電話去修故障,關鍵在於一開始的架構設計要設計成一個雙活或者多活,使得你們的工做更加的輕鬆,更加不須要人肉或者緊急修理。
能夠舉另一個例子,好比你們有些時候會糾結安全,由於平時用的 Linux 、 Windows 在設計之初就不是安全的。在前幾年出了一個 seL4 的新操做系統,它是從設計之初就考慮安全的,因此它得到了最高級的安全認證: EAL6 、世界惟一的一個最高級安全認證。從設計開源之後到如今那麼多年,它是被數學證實安全的,到如今爲止尚未發現它的漏洞。這就是設計出發點和設計基礎不一樣,因此會致使最後有不少工做的不一樣。最安全的操做系統,沒有人發現有安全漏洞,由於它是從新按照安全去設計的。可是, Linux 或者是 Windows ,它設計之初就是爲了趕時間,不少安全沒有考慮,因此後面各類各樣的漏洞就被發現出來,這個例子就是基礎不一樣致使的結果不一樣。
個人分享就到這裏,謝謝你們!