Ribbon
我們首先對Ribbon 進行一個介紹。
Spring Cloud Ribbon 是一個基于 HTTP 和 TCP的用戶端負載均衡工具, 它不同于Nginx的服務端負載均衡,他側重于将需要的通路清單從服務注冊中心中取出,放在自己的通路伺服器清單(ServerList)中,當需要通路某一台具體的伺服器的時候,他會經過不同的輪詢政策去通路相應的負載均衡裝置。Ribbon适合于日通路量并不高的系統中。
同時他也不同于硬體設施的負載均衡,硬體設施經常通過配置citrix netscaler, 負載均衡路由器,或者實作可循環的DNS 進而實作輪詢算法,配置設定流量給各個節點。軟體端的負載均衡,包括Nginx或者Ribbon,他們通過用代碼實作輪詢算法的政策,進而實作小規模的任務配置設定,軟體的負載均衡具有可重用,費用低和易維護等特點,當然,他的缺點也很明顯,隻能實作小規模的負載均衡,換句話說隻能小打小鬧,而不能對性能做一個跨越性的提升。
Ribbon 在Spring Cloud中的使用
Ribbon在Spring Cloud 可以通過@LoadBalanced 服務端接口,實作用戶端的負載均衡,當用戶端發起對服務端的請求通路的時候,可以通過Ribbon的負載均衡,選擇不那麼繁忙的伺服器去進行請求處理。
LoadBalaced注解采用了RestTemplate 的服務通路模式,因為是RestTemplate,是以它可以選擇傳回是Response 對象,還是一個已經被申明屬性的對象,或者直接是一個URI。RestTemplate 有四種常用通路方法,get,post,delete和put。
Ribbon 負載均衡政策
- 随機均衡( random Rule):随機均衡是指 Ribbon 可以從ServerList 中随機選取伺服器進行配置設定任務,這種選擇方法實作起來簡單,但很容易因為取不到伺服器而陷入死循環中。
- Ribbon 輪詢均衡 (Round Ribbon Rule)該政策實作了按照線性輪詢的方式去通路伺服器,每個伺服器的通路次數幾乎相等,對于任務時間長度相差不大的情況下,這種輪詢政策不耗費時間,當然缺點也很明顯,容易因為取不到伺服器而陷入到死循環中。
- 重試均衡(Retry Rule)重試均衡本質上實作了Ribbon輪詢均衡的算法,不同點是他定義了一個TimeOut的時間,首先使用輪詢均衡取得伺服器,如果取不了,則重新選取,過了一個規定的時間門檻值後仍然取不了,則宣告通路失敗,傳回null值。
- 權重響應時間均衡(weighted Response Time Rule) 這個政策每30秒計算一次伺服器響應時間,以響應時間作為權重,響應時間越短的伺服器被選中的機率越大。
- 最空閑均衡(Best Available Rule) 他首先周遊所有的伺服器,通過周遊找出并發量最小的哪一個,再把任務配置設定給這個伺服器。
- 預測均衡(PredictedBased Rule) 雖然叫做預測算法,但是實際上跟預測關系不大,他是線過濾一輪伺服器,将高并發的伺服器排除在外,然後實作前面的輪詢均衡算法,也就是線性選擇伺服器。
- 可用過濾均衡(availablityFilteringRule)他繼承了預測均衡,同時在預測均衡的基礎條件上,增加了兩個基本過濾條件,第一是判斷斷路器Hystrix 是否生效斷開,第二是判斷并發請求數是否大于門檻值
- 區域避免均衡 (zoneAvoidance Rule)該政策主要是在在多區的條件下使用,選擇出最佳區域的執行個體通路。他首先使用ZoneAvoidancePredicate 進行過濾,此為主過濾,同時他也使用AvailbilityPredicate 作為次要過濾條件,作為次要過濾。
負載均衡政策等級關系圖:
SpringCloud學習總結之 Ribbon 和 Hystrix (三) Ribbon負載均衡的重試機制
因為Eureka 的限制,Spring Cloud 很難達到所有分片一緻,于是他們整合Spring retry 機制來增強RestTemplate 的重試能力,盡量達到分片一緻。
Spring retry 基本配置如下:
spring.cloud.loadbalancer.retry.enabled=true //開啟retry
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
//斷路器的逾時時間
sf-springcloud-service.ribbon.ConnectTimeout=250
sf-springcloud-service.ribbon.ReadTimeout=1000
sf-springcloud-service.ribbon.OkToRetryOnAllOperations=true
// 所有操作請求是否都采用重試
sf-springcloud.ribbon.MaxAutoRetriesNextServer=2
// 切換執行個體的最大次數
sf-springcloud.ribbon.MaxAutoRetries=1
//目前執行個體重試的最大次數
Hystrix
Hystrix 是由Martin Fowler提出的,他指的是當一個伺服器存在響應緩慢或者響應失敗的情況下,Hystrix能夠及時發現并傳回錯誤響應,而不是長時間的等待。是以Hystrix 涉及兩個動作,發現故障,傳回錯誤響應。
Hystrix 流程圖
SpringCloud學習總結之 Ribbon 和 Hystrix (三) - Hystrix 通過HystrixCommand 或者HystrixObservableCommand 對象實作對于熔斷的依賴。HystrixCommand 和HystrixObservableCommand 是不同的操作,HystrixCommand 用在依賴的服務傳回單個操作結果, 而HystrixObservableCommand 用在以來的服務傳回多個操作結果的時候。
-
下一層代表的是指令執行方式:
Execute() 同步執行
Queue() 異步執行,傳回一個Future對象
Observe() 傳回Observable對象,傳回HotObservable
ToObserve() 執行也是傳回一個Observable 對象,但是傳回的是cold Observable
Hot Observable 是指無論有沒有觀察者進行訂閱,事件始終都會發生,他與訂閱者是一對多的關系,當存在多個Observable的時候,事件不獨立。Cold Observable 是指觀察者訂閱後,才會進行發射資料流,他與訂閱者是一對一的關系,并且是獨立的。
- 判斷是否存在緩存中
- 檢測斷路器是否打開,如果斷路器打開了,則跳轉到fallback進行操作,如果沒有,則進行判斷斷路器沒有打開的原因
- 判斷斷路器是否因為線程池/請求隊列和信号量的原因沒有打開。 Hystrix它采用的是艙壁模式,是以此處判斷的線程池,不是容器的線程池,而是每一個依賴服務特有的容器池
- 請求依賴服務
- 主要是計算伺服器是否需要熔斷或重新開啟,他通過四種狀态與短路器溝通,成功,失敗,拒絕和逾時。
- 如果熔斷,執行fallback服務降級,服務降級就是一般是從整體來進行考慮,因為伺服器熔斷後,将不再被調用,此時候用戶端可以自己準備一個default value 的fallback 傳回調用,雖然不太準确,但可以確定服務還可用,不至于影響其他回調。能夠觸發降級調用的事件有三件,分别是依賴是否開啟,斷路器是否打開,線程池/請求隊列或信号量是否占滿。
- 傳回正确結果
Hystrix 依賴隔離
依賴隔離的目标是避免系統某一部分發生故障,進而使整個系統癱瘓。 該詞語最先來自将船舶劃分為單獨的水密艙室以避免将單個船體破損淹沒整艘船舶的船舶;
依賴隔離可以通過線程和信号量來實作,Hystrix為所有依賴都建立線程池,使得依賴之間互相隔離,同時通過限制他們的并發通路次數來達到阻塞擴張的目的。線程可以通過重要度來進行權限配置設定,這使得重要的依賴可以最優先被響應,每一部分的依賴出現了問題,也不會影響其他依賴的使用資源。
信号量隔離是指在通路伺服器之前,得到準許,如果沒有準許則不可以通路。