Netflix如何在上萬臺機器中管理微服務?

​任何一個普通的服務,放到 Netflix 的大規模集羣(上萬臺機器)裏運行,如果不做特別處理,會發生各種各樣的問題,以實現一個電影推薦的服務爲例,傳統方案:

在傳統的方案裏,你會使用固定 DNS 域名解析服務,將一組固定的 IP 放在負載均衡的列表裏。服務註冊和發現都是寫在配置文件裏,一旦服務掛掉了,依賴於這個服務的其他服務都會受到影響,傳統的辦法只能新起一臺服務器,然後去改變其他機器的配置文件,並重啓關聯的服務。

在小的集羣裏這種方式或許可以忍受,但在上萬臺服務器的集羣裏,管理500多種服務的時候,情況將變得非常複雜,Netflix 通過多年的實踐,貢獻出了很多開源項目,例如:Eureka, Hystrix, Feign,Ribbon 等等, 來解決大規模集羣裏服務管理的問題。

使用 Eureka 作爲服務發現工具

Eureka 是什麼?

Eureka 是 Netflix 貢獻出來的開源中間層負載均衡和服務發現的工具。Eureka 基於 Java 實現,可以非常方便的在 Spring 應用程序裏聲明 Server 和 Client 進行服務註冊。

Eureka 解決的問題

Eureka 服務器是服務的註冊中心,它能提高大規模集羣環境裏服務發現的容錯性和可用性。並且可以解決跨數據中心之間的服務註冊和發現的問題。

Netflix 推薦在每個 Region 搭建一個 Eureka 集羣,每個 Region 裏的可用區至少有一個 Eureka Server,這樣可以保證任意一個可用區的服務註冊信息都會被複制到各個可用區,實現服務信息的高可用。在任意可用區的客戶端都可以訪問到服務的註冊信息。客戶端在訪問服務器之後會在本地緩存服務的信息,並且定期(30秒)刷新服務的狀態。

如果在集羣內有大面積的網絡故障時(例如由於交換機故障導致子網之間無法通信),Eureka 會進入自我保護模式,每個Eureka節點會持續的對外提供服務(注:ZooKeeper不會):接收新的服務註冊同時將它們提供給下游的服務發現請求。這樣就可以實現在同一個子網中(Same side of partition),新發布的服務仍然可以被發現與訪問。

在 Eureka V1.0的版本里,Eureka 之間的數據同步是全量同步,每個客戶端都有 Eureka 集羣裏所有服務的信息,在 V2.0的版本里,將支持客戶端偏好的服務信息同步。同時也會增強 Eureka 的讀寫分離和高可用性。

有了 Eureka,Netflix 如何做紅黑髮布?

Netflix 發佈的方式是紅黑髮布。如果監控到線上部署的服務有問題,按傳統方式回滾一個服務需要5-15分鐘。而 Netflix 使用 Eureka 能夠動態的下線/上線一個服務。

服務分兩種:REST 服務和非 REST 服務。如果下線的服務是 REST 服務,那麼情況比較簡單,通過 Eureka 可以實時的實現服務的下線和上線。

如果服務是非 REST 服務,例如執行 Batching 任務或者快服務的 Transaction 等等,就不能簡單的標記服務下線,藉助於 Spring 提供的 EventListener (事件監聽器),Eureka 可以傳遞
EurekaStatusChangeEvent 事件,幫助開發者在這個事件監聽器裏去做對應的服務下線處理。

Netflix 在實現紅黑髮布的時候,會先將一部分的服務動態下線,如果這些服務有一些 Batching 任務,則通過事件監聽器停掉這些任務。

爲什麼 Netflix 沒有選擇使用 ZooKeeper 做服務發現?

因爲當 ZooKeeper 在處理上千個節點時,由於故障發生次數不高,可能可以應對,但是達到上萬節點之後,ZooKeeper 的表現不如 Eureka,因爲在這種體量的集羣裏,集羣故障是時刻都在發生的,如果每次都重新進行選舉的代價太大,而 Eureka 會根據 CAP 理論中的 AP 策略,採用了最終一致的方案。

其次,Eureka 提供了 REST endpoint 支持服務的註冊,這樣解決能 Non-Java 服務的註冊問題。

Hystrix 做服務降級

Hystrix 是 Netflix 開源的組件,它能夠幫助服務之間調用超時,報錯時,阻止問題的擴散,避免雪崩。在用戶無感知的情況下對服務進行降級處理。

舉例:當你試圖爲你的用戶進行電影推薦時,出於某種原因服務調用一直沒有返回(可能依賴的 User 服務掛了),Hystrix 可以定義多種策略來判斷服務是否健康。例如:爲 Hystrix 預設一個 timeout 時間,如果服務調用的返回結果超過這個時間,Hystrix 會決定觸發熔斷機制,暫定該服務的調用,並返回一個通用的電影列表作爲推薦,而不是讓用戶無休止的等下去,從而提高用戶體驗。

當然,超時時間只是 Hystrix 做熔斷決策的一個條件,你可以爲 Hystrix 設置多個條件來讓判斷某個服務調用是否正常,比如服務的 corePoolSize, maximumPoolSize and keepAliveTime 都可以作爲 Hystrix 熔斷的策略。

Hystrix 提供了 Circuit Break 來檢測服務的健康狀態,Circuit Break 解決了以下問題:

  1. 檢查服務的狀態。
  2. 支持線程和資源訪問的隔離。當服務的併發訪問特別大時(每秒上百個連接),Circuit Break 會對線程進行隔離,或者對資源訪問做限制,保證服務的可用性。

下圖是 Circuit Break Open/Close 的決策流程:

  1. 如果服務調用的錯誤率高於預先設置的錯誤率。
  2. Circuit-breaker 的狀態會從 CLOSED 變成 OPEN(熔斷狀態)。
  3. 當 Circuit-breaker 狀態爲 OPEN 時,所有進來的請求會被阻止。
  4. 過一段時間,會讓一些單個的請求進來(Half-Open),如果服務調用仍然失敗,Circuit-breaker 會再次進入 OPEN 狀態,如果請求成功,Circuit-breaker 狀態變爲 CLOSED 並且重新進入第一步。

目前,Hystrix 正在對跨服務事務(Transaction)處理進行優化中。

Ribbon 作爲負載均衡

Ribbon 是 Netflix OSS 貢獻的處理 RPC 調用的軟負載均衡。除了傳統負載均衡的能力之外,它還能解決以下問題:

  1. 當監控到集羣內有9臺服務器提供同一個服務,其中有三臺的響應明顯有問題,Ribbon 可以臨時將這三臺服務器從負載均衡中剔除,直到這三臺機器恢復正常的響應。

  2. 可以對響應最快的服務器進行加權,將更多的流量帶到響應最快的節點。

  3. 支持將多種負載均衡的策略同時啓用,將負載均衡的效果調試到最好。

  4. 自定義設置重試機制。

雖然 Ribbon 項目處於維護狀態,但是它的實現思路仍然值得大家借鑑。

總結

本文主要介紹了 Netflix OSS 貢獻的 Eureka,Hystrix 和 Ribbon,由於篇幅限制,其他的組件將在後續的文章中介紹, 這些開源組件和 Spring Boot/Spring Cloud 都有良好的集成,通過註解的方式配合 Properties 文件,能夠解決管理大規模服務時遇到的通用問題。

本文的目的是希望通過解讀 Netflix 在實現大規模擴容時遇到的問題,分析他們的解決辦法,爲將來自己碰到問題時提供一些思路,思路和視野有時候比工具本身更重要。

下載JFrog Artifactory 開源版(代替 Nexus):
http://www.jfrogchina.com/open-source/

下載JFrog Artifactory 企業版(免費試用):
https://www.jfrog.com/artifactory/free-trial/?lang=zh-hans#High-Availability

參考資料:
https://github.com/Netflix/eureka/wiki
https://github.com/Netflix/Hystrix

延伸閱讀:
谷歌大神爲你解釋Kubernetes, 微服務和容器化

每天發佈1000次變更 - Netflix 的微服務實踐和經驗

傳統 Java 網站如何實現容器化?看看 Cars.com 如何玩轉 Docker!

關於JFrog
世界領先DevOps平臺
公司成立於2008年,在美國、以色列、法國、西班牙,以及中國北京市擁有超過200名員工。JFrog 擁有3000多個付費客戶,其中知名公司包括如騰訊、谷歌、思科、Netflix、亞馬遜、蘋果等。關注 JFrog,感受原汁原葉的硅谷技術!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章