微服務實踐:服務治理

微服務實踐:服務治理

在微服務的演進過程中,爲了最大化利用微服務的優勢,保障系統的高可用性,需要通過一些類的服務支撐組件來協助服務間有效的協作,這便是服務治理的範疇。

註冊發現

爲什麼需要服務註冊發現

  在微服務系統中,服務的消費者需要知道服務提供者的網絡地址,才能與之通信。比較簡單的實現方式是直接在消費者端或者負載均衡器上進行註冊,在發生變化時手動更新。隨着服務數量的增多,這種方式會面領如下挑戰:

  • 手動註冊實例地址的成本高
  • 無法識別服務重啓後的網絡地址的變化

服務註冊發現——客戶端發現

  當服務發現的邏輯位於服務消費者端時,稱爲客戶端發現。服務發現簡單來說,服務註冊發現的過程(客戶端發現),共分爲以下3個步驟:

  

  1、 服務提供者將實例信息註冊到註冊中心。

  2、服務調用者根據服務標識,從註冊中心查詢服務,獲取包含網絡地址的服務實例列表

  3、與服務實現通信。

   客戶端發現的缺點是實現起來較爲複雜,因爲在各個服務消費者中需要完成以下功能:首先需要維護服務提供者的列表,並且需要不斷與註冊中心同步以獲取服務最新信息;其次,如果服務部署多實例,服務消費者需要實現路由邏輯,即實現負載均衡器。

服務註冊發現——服務端發現

  

  1、 服務提供者實例向註冊中心註冊地址信息。

  2、調用者向服務發送請求,請求被送到負載均衡器。

  3、負載均衡器從服務註冊中心查找服務體用這注冊的信息。

  4、負載均衡器將請求轉發給具體的服務提供者實例。

  服務端發現的好處是服務消費者的實現複雜度會降低。服務消費者只需要發送請求,不需要關心如何與註冊中心交互。缺點是由於多個請求多了一次網絡跳轉,整體性能會有所損失,需要保證它的高可用性。

 

負載均衡

什麼是負載均衡

  爲了提高可用性、降低延遲,同一個服務可能會部署多個實例,負載均衡就是爲了在服務的多個實例之間進行分配負載,已達到優化資源使用、最大化吞吐率,同時避免過載。

服務端負載均衡

  優點是負載均衡對於服務消費者來說是透明的,服務消費者完全感知不到負載均衡的存在,也不需要關心具體被轉發至哪個實例。但是當服務數量或調用了增大時,一旦負載均衡器發生故障就導致整個系統不可用。常見的複雜均衡器有如下:

  

 

  還有一些商用的負載均衡器,如F5、NetScaler、Array、AWD的ELB、華爲雲的ELB等。

客戶端負載均衡

  將負載均衡的功能以庫的形式集成到服務消費中。服務消費者需要訪問某服務時,需要通過內置的負載均衡組件向服務註冊中心查詢,得到可用的服務提供者列表,然後按照某種負載均衡策略選擇一個目標服務地址,最後向目標服務發起請求。

  

 

  服務端負載均衡將負載均衡能力實現在服務內部,因此服務消費者與提供者之間是直接調動,沒有額外開銷,性能較好。目前客戶端負載均衡在很多開源框架中都有實現,如Spring Cloud、Dubbo、ServiceComb等。

負載均衡策略

  • 隨機策略
  • 輪詢策略
  • 權重策略
  • 響應事件策略

 

配置管理

   服務在運行過程中,需要和其他服務協作,同時他也會依賴基礎設施或其他服務完成某項業務功能。在這個過程中,就需要多樣化的配置信息。

  • 基礎設施的連接信息
  • 協作服務的地址信息
  • 業務行爲的配置參數
  • 與特性相關的信息

  源碼中硬編碼配置信息,雖然實現成本低,但是這種方式不僅缺乏靈活性,而且容易造成信息泄露。因此,較好的方式是將配置與代碼分離。採用獨立於代碼的外部機制存儲配置信息。

微服務的配置管理策略

  下圖爲集中化的配置管理示意圖:

  

  其配置變更流程如下:

  

 

多實例的配置信息變更

  對於服務多實例的場景,可以引入輕量級的消息代理,通過廣播事件或者消息的方式通知各個實例更新配置。

  

 

容錯機制

  生產環境中的每個微服務並不是具有百分百的可靠性。一方面,線性系統的可靠性等於其所包含的每個組件的可靠性之乘積,而各個微服務之間存在錯綜複雜的關係,讓它比線性系統更復雜。另一方面,服務之間跨網絡調用,增加了調用失敗的可能性。因此,如何保證微服務系統的可靠性,也變得更爲複雜和困難。所以,微服務系統在設計之初就需要考慮容錯機制,當系統負載過高時,可以確保核心業務不被破壞,以及當某個服務出錯時,把影響範圍降低到最小,避免整個系統不可用。下面介紹一下常見的容錯模式。

限流

  服務的流量可能是動態的,如果流量增加,超過服務承載範圍,就會影響用戶掩。通過限制服務能使用的資源,當監控到流量超過設定的閾值時,服務拒絕處理新的用戶請求。當系統壓力過大時,對系統的非核心業務進行限流,避免因壓力過大導致整個系統奔潰。

超時和重試

  超時時指當前消費者依賴的服務出現響應延遲時,消費者不用無限等待,而是根據事先設計的超時時間中斷調用,及時釋放Web容器、數據庫等的連接資源。重試通常與超時結合起來,當出現超時時重新發起調用,常用於因網絡抖動等導致服務調用出現超時的場景。

  服務雪崩現象如下:

  

 

  服務提供者不可用——>重試加大流量——>服務消費者不可用

  對於服務提供者來說,可通過自動擴容和限流來應對。對於服務消費者來說需要引入服務降級來避免服務雪崩,具體措施包括隔離、熔斷和回退。

服務隔離

  微服務架構下系統會包含多個服務,每個服務擁有一個或多個消費者,服務負載過多或故障將影響所有消費者。消費者可以同時向多個服務發送請求,每個請求都消耗資源。當消費者向錯誤配置或未響應的服務發送請求時,客戶端請求使用的資源可能無法及時釋放,繼續對服務請求會耗盡資源,如耗盡客戶端的連接池,導致消費者對其他服務的請求也受到影響,進而不能再向其他服務發送請求

  在軟件行業中,可以考慮通過資源隔離來防止有限的資源被耗盡:

  

 

  服務A依賴於服務B、C、D,假設運行服務A的容器有120個線程,當服務B不可用時,服務A重試或外部流量增加,服務A的120個線程會因爲服務B的不可用而耗盡。

  如果採用線程隔離的機制,對於服務B、C、D的調用使用不同的連接池,每個服務各分配40個線程。當服務B不可用時,爲服務B分配的線程會被耗盡,而爲服務C、D分配的80個線程不受影響,服務A仍然可用。

   

 

   使用隔離機制的好處在於:

  • 防止引發服務級聯故障
  • 在發生服務故障的時保留一些功能,系統的其他服務和功能將繼續運行。

  

熔斷和回退

  當電路發生短路時,斷路器能夠主動熔斷電路,以避免災難發生。借用斷路器的原理,引入熔斷機制,在服務出現非臨時性的故障時,先通過回退機制(直接返回錯誤、返回空值/缺省值、返回緩存/備份數據)防止重複嘗試執行可能失敗的操作,同時檢測故障是否持續,是否已解決。如果問題已經修復,則重新發起請求。

  熔斷機制可以通過「代理 → 斷路器」統計最近發生的故障數,來決定是否繼續操作或者返回異常。如圖 3-40 所示,斷路器的狀態包括關閉狀態、打開狀態和半開狀態。

   

 

   ● 關閉狀態:在默認情況下,斷路器處於關閉狀態,如果調用持續出錯,失敗計數器在給定時間段內超過了閾值,斷路器進入打開狀態

  ● 打開狀態:在指定時間段內,不再向服務提供者發送請求,而是直接回退到失敗的結果,此時斷路器進入打開狀態,並且啓動超時計時器。

  ● 半開狀態:計時器超時後,斷路器進入半開狀態,即允許發送少量請求進行嘗試,並且通過成功計數器計算成功的請求數。如果調用仍然失敗,則返回到打開狀態,如果成功計數器超過閾值,則斷路器回到關閉狀態

   熔斷機制提供穩定性,讓服務從故障中恢復,並最大限度地減少性能的影響。這種機制可定製性較強,可以根據故障類型進行調整。例如,可以將超時計時器的超時時間逐步增加。最初可以將斷路器置於打開狀態幾秒鐘,然後如果故障沒有解決,將超時時間增加到幾分鐘。