1、SpringCloud Ribbon概述
Spring Cloud Ribbon是一個進行用戶端的LoadBalance負載均衡元件,基于HTTP和TCP用戶端。它雖然隻是一個工具類庫,并不需要像eureka注冊中心、網關服務那樣單獨部署,但它卻是每一個微服務的基礎設施。因為實際上,對于服務間調用、API網關請求轉發都需要經過Ribbon負載均衡來實作,比如我們熟悉的Feign發送請求也得經過它。負載均衡是網際網路開發避不開的核心概念之一,它是HA高可用的最有效手段。而在微服務日益流行的今天,對Ribbon的了解和使用,對于我們建構微服務非常重要。
Ribbon是一個内置LoadBalance平衡器的程序間通信(遠端過程調用)庫。Ribbon用戶端元件提供一系列完善的配置項如連接配接逾時,重試等。簡單的說,Ribbon是一個用戶端負載均衡器,我們可以在配置檔案中Load Balancer後面的所有機器,Ribbon會自動的幫助你基于某種規則(如簡單輪詢,随機連接配接等)去連接配接這些機器,我們也很容易使用Ribbon實作自定義的負載均衡算法。
Spring cloud有兩種服務調用方式,一種是ribbon+restTemplate,另一種是feign。
2、Ribbon 負載均衡
目前微服務分布式架構下,下遊服務通常會建立多個副本執行個體,每個副本都在另一台計算機上運作。此時,出現 Load Balancer(負載均衡器),根據負載政策将上有服務請求映射到每一個副本上,它有助于在伺服器之間平均配置設定傳入流量。
2.1 用戶端負載均衡和服務端負載均衡
用戶端負載均衡和服務端負載均衡最大的不同在于服務清單所在的位置。用戶端負載均衡中,用戶端中都維護着自己要通路的服務段清單,而這些清單都來源于服務注冊中心,但是服務端負載均衡的服務清單是無法自己來維護的。
(1) 服務端負載均衡器
傳統上,Load Balancers(例如Nginx、F5)是放置在伺服器端的元件。當請求來自 用戶端 時,它們将轉到負載均衡器,負載均衡器将為請求指定 伺服器。負載均衡器使用的最簡單的算法是随機指定。在這種情況下,大多數負載平衡器是用于控制負載平衡的硬體內建軟體。
特點:
- 服務端位址對用戶端透明,用戶端不知道伺服器端的服務清單,甚至不知道自己發送請求的目标位址存在負載均衡器。
- 伺服器端維護負載均衡伺服器,控制負載均衡政策和算法。
(2)用戶端負載均衡器
當負載均衡器位于 用戶端 時,用戶端得到可用的伺服器清單然後按照特定的負載均衡政策,分發請求到不同的 伺服器 。

特點:
- 用戶端需要知道伺服器端的服務清單(可能通過配置、可能讓其自己去注冊中心拉取),需要自行決定請求要發送的目标位址。
- 用戶端維護負載均衡伺服器,控制負載均衡政策和算法。
2.2 負載均衡器分類
-
BaseLoadBalancer
BaseLoadBalancer類時Ribbon服務均衡器的基礎實作類,在該類中定義了很多關于負載均衡器光宇的基礎内容。
-
DynamicServiceListLoadBalancer
DynamicServiceListLoadBalancer負載均衡器時對BaseLoadBalancer的擴充。
-
ZoneAwareLoadBalancer
ZoneAwareLoadBalancer負載均衡器時對DynamicServiceListLoadBalancer的擴充。
springcloud — 微服務負載均衡元件之Ribbon
2.3、負載均衡政策
IRule時負載均衡政策的接口,AbstractLoadBalancerRule是負載均衡政策的抽象類。下面我們看一下幾個具體的實作類:
- RandomRule: 實作了從服務執行個體清單中随機選擇一個服務執行個體的功能
- RoundRobinRule:實作了按照線性輪詢的方式一次選擇每個服務執行個體的功能
- RetryTule:實作了一個具備重試機制的執行個體選擇功能
- WeightedRespinseTimeRule:該政策是對RoundRobinRule的擴充,增加了根據執行個體的運作情況來計算權重,并根據權重來挑選執行個體,已達到更優的配置設定效果。
- ClientConfigEnabledRoundRobinRule:該政策較為特殊,我們一般不直接使用它。因為它本身并沒有實作什麼特殊的處理邏輯,真如代碼中所示,在他的内部定義了一個RoundRobinRule政策,而choose函數的實作也正是使用了RoundRobinRule的線性輪詢機制,是以它實作的功能實際上RoundeRobinRule相同。雖然不能直接使用該政策,但是可以通過繼承該政策,預設的choose就實作了線性輪詢機制,可以在子類中實作更進階的政策;
- BestAvailableRule:該政策通過周遊負載均衡器中維護的所有執行個體,會過濾調故障的執行個體,并找出并發請求數最小的一個,是以該政策的特征是選擇出最空閑的執行個體;
- PredicateBaseRule:先通過子類中實作的Predicate邏輯來過濾一部分服務執行個體,然後再以線性輪詢的方式從過濾後的執行個體清單中選出一個。至于如何過濾,需要我們在AbstractServerPredicate的子類中實作apply方法來确定具體的實作政策。
-
ZoneAvoidanceRule:它是PredicateBaseRule的具體實作類,從它的源碼中可以看到它是通過CompositePredicate來進行服務執行個體清單過濾的。這是一個組合過濾條件,在其構造函數中,ZoneAvoidancePredicate為主過濾條件,AvailabilityPredicate為次過濾條件初始化了組合過濾條件的執行個體。
ZoneAvoidanceRule在實作的時候并沒有像AvailabilityFilteringRule那樣重寫choose函數來優化,它遵循:“先過濾清單,再輪詢選擇”。其中過濾清單的條件就是我們上面提到的以ZoneAvoidancepredicate為主過濾條件,AvailabilityPredicate為次過濾條件的組合過濾條件。從CompositePredicate的代碼片段中,我們可以看到它定義的一個主過濾條件AbstraServicePredicate Delegate以及一組次過濾條件清單listfallbacks,是以它的此過濾清單是可以擁有多個的,并且由于它采用了List存儲是以次過濾條件是按順序執行的。
3、Ribbon實踐
基礎環境:
SpringCloud 版本 Finchley.RC1
SpringBoot 版本 2.0.1.RELEASE
添加Ribbon依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
application.yml配置:
server:
port: 8381
spring:
application:
name: spring-demo-service-ribbon
spring-demo-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
啟動類:
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
/**
* 向容器中注入 restTemplate,同時通過 @LoadBalanced 開啟 restTemplate 負載均衡功能
* @return
*/
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
在啟動類中,通過@EnableDiscoveryClient 向 consul 注冊,并向容器中注入 restTemplate,同時通過 @LoadBalanced 開啟 restTemplate 負載均衡功能。
測試service類:
@Service
public class SpringDemoRibbonService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "portFallback")
public String port() {
return restTemplate.getForObject("http://SPRING-DEMO-SERVICE/port", String.class);
}
public String portFallback() {
return "sorry ribbon, it's error!";
}
}
這裡我們啟動了兩個spring-demo-service服務,實作一個簡單的port接口進行遠端調用,然後在浏覽器中多次通路 localhost:8381/hello,效果如下:
此時說明基本使用 Ribbon 實作了用戶端負載均衡的功能,當用 restTemplate 調用服務接口時,通路了不同端口的服務執行個體。
4、Ribbon子產品說明
ribbon五大元件:
- ServerList:可以響應用戶端的特定服務的伺服器清單
- ServerListFilter:可以動态獲得的具有所需特征的候選伺服器清單的過濾器
- ServerListUpdater:用于執行動态伺服器清單更新
- IRule:負載均衡政策,用于确定從伺服器清單傳回哪個伺服器
- IPing:用戶端用于快速檢查伺服器當時是否處于活動狀态(心跳檢測)
- ILoadBalancer:負載均衡器,負責負載均衡排程的管理
說明,以上核心元件所在的Jar其實是ribbon-loadbalancer,它包含ribbon-core,更面向于應用層面,是以一般都會使用它。
Ribbon 依賴包中Modules子產品:
- ribbon-core:用戶端配置api和其他共享api
- ribbon-loadbalancer:可以獨立使用或與其他子產品一起使用的負載均衡器api
- ribbon:內建了負載平衡、容錯、緩存/批處理等功能的api
- ribbon-eureka:使用Eureka用戶端為雲提供動态伺服器清單的api
- ribbon-httpclient:REST用戶端建構在Apache HttpClient之上,與負載平衡器內建(不支援并被ribbon子產品取代)
- ribbon-transport:使用具有負載平衡功能的RxNetty傳輸支援HTTP、TCP和UDP協定的用戶端
引用: https://www.springcloud.cc/spring-cloud-greenwich.html#spring-cloud-ribbon https://blog.csdn.net/f641385712/article/details/104761814