一. Ribbon概述
Spring Cloud Ribbon是基于Netflix Ribbon 實現(xiàn)的一套客戶端的負載均衡工具,Ribbon客戶端組件提 供一系列的完善的配置,如超時,重試等。通過Load Balancer獲取到服務(wù)提供的所有機器實例, Ribbon會自動基于某種規(guī)則(輪詢,隨機)去調(diào)用這些服務(wù)。Ribbon也可以實現(xiàn)我們自己的負載均衡算法。
二. 主流負載均衡
- 集中式負載均衡
在消費者和服務(wù)提供方中間使用獨立的代理方式進行負載,有硬件的(比如 F5),也有軟件的(比如 Nginx)。
- 客戶端負載均衡
客戶端會有一個服務(wù)器地址列表,在發(fā)送請求前通過負載均衡算法選擇 一個服務(wù)器,然后進行訪問,這是客戶端負載均衡。
三. 常見負載均衡算法
算法就是從服務(wù)列表中按某個規(guī)則選取一個。
隨機,通過隨機選擇服務(wù)進行執(zhí)行,一般這種方式使用較少;
輪訓,負載均衡默認實現(xiàn)方式,請求來之后排隊處理;
加權(quán)輪訓,通過對服務(wù)器性能的分型,給高配置,低負載的服務(wù)器分配更高的權(quán)重,均衡各個 服務(wù)器的壓力;
地址Hash,通過客戶端請求的地址的HASH值取模映射進行服務(wù)器調(diào)度。
最小鏈接數(shù),即使請求均衡了,壓力不一定會均衡,最小連接數(shù)法就是根據(jù)服務(wù)器的情況,比如請求積壓數(shù)等參數(shù),將請求分配到當前壓力最小的服務(wù)器上。
服務(wù)每處理一個請求,請求數(shù)+1,處理完-1. 新的請求來時選擇請求數(shù)最少的處理。這樣性能最好的服務(wù)器接收最多的請求。
四. Ribbon 模塊
- ribbon- loadbalancer
負載均衡模塊,可獨立使用,也可以和別的模塊一起使用。 Ribbon 內(nèi)置的負載均衡算法都實現(xiàn)在其中。
- ribbon-eureka
基于 Eureka 封裝的模塊,能夠快速、方便地集成 Eureka。
- ribbon-transport
基于 Netty 實現(xiàn)多協(xié)議的支持,比如 HTTP、Tcp、Udp 等。
- ribbon-httpclient
基于 Apache HttpClient 封裝的 REST 客戶端,集成了負載均衡模塊,可以直接在項目中使用來調(diào)用接口。
- ribbon-example
Ribbon 使用代碼示例,通過這些示例能夠讓你的學習事半功倍。
- ribbon-core
一些比較核心且具有通用性的代碼,客戶端 API 的一些配置和其他 API 的定義。
五. Ribbon 使用
5.1 直接使用
// 服務(wù)列表
List<Server> serverList = Lists.newArrayList(
new Server("localhost", 8020),
new Server("localhost", 8021));
// 構(gòu)建負載實例
ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder()
.buildFixedServerListLoadBalancer(serverList);
// 調(diào)用 5 次來測試效果
for (int i = 0; i < 5; i++) {
String result = LoadBalancerCommand.<String>builder()
.withLoadBalancer(loadBalancer).build()
.submit(new ServerOperation<String>() {
@Override
public Observable<String> call(Server server) {
String addr = "http://" + server.getHost() + ":" +
server.getPort() + "/order/findOrderByUserId/1";
System.out.println(" 調(diào)用地址:" + addr);
URL url = null;
try {
url = new URL(addr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.connect();
InputStream in = conn.getInputStream();
byte[] data = new byte[in.available()];
in.read(data);
return Observable.just(new String(data));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}).toBlocking().first();
System.out.println(" 調(diào)用結(jié)果:" + result);
}
}
5.2 Spring Cloud快速整合Ribbon
<!‐‐添加ribbon的依賴‐‐>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐starter‐netflix‐ribbon</artifactId>
</dependency>
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/findOrderByUserId/{id}")
public R findOrderByUserId(@PathVariable("id") Integer id) {
String url = "http://mall‐order/order/findOrderByUserId/"+id;
R result = restTemplate.getForObject(url,R.class);
return result;
}
六. Ribbon原理
Ribbon 本質(zhì)上是基于RestTemplate 的擴展點,攔截原本請求后,利用負載均衡算法在服務(wù)列表中選出一個服務(wù),替換服務(wù)名實現(xiàn)負載均衡調(diào)用的。

@LoadBalanced 原理
1.LoadBalancerAutoConfiguration 自動注入
2.@LoadBalanced利用@Qualifier作為restTemplates注入的篩選條件,篩選出具有負載均衡標識的 RestTemplate。
被@LoadBalanced注解的restTemplate會被定制,添加LoadBalancerInterceptor攔截器。
image.png
七. Ribbon 相關(guān)接口
源碼入口RibbonClientConfiguration
- IRule:Ribbon的負載均衡策略,默認采用ZoneAvoidanceRule實現(xiàn),該策略能夠在多區(qū)域環(huán)境下選出 最佳區(qū)域的實例進行訪問。
- IPing:Ribbon的實例檢查策略,默認采用DummyPing實現(xiàn),該檢查策略是一個特殊的實現(xiàn),實際上 它并不會檢查實例是否可用,而是始終返回true,默認認為所有服務(wù)實例都是可用的。
- ServerList:服務(wù)實例清單的維護機制,默認采用ConfigurationBasedServerList實現(xiàn)。
- ServerListFilter:服務(wù)實例清單過濾機制,默認采ZonePreferenceServerListFilter,該策略能夠優(yōu)先 過濾出與請求方處于同區(qū)域的服務(wù)實例。
- ILoadBalancer:負載均衡器,默認采用ZoneAwareLoadBalancer實現(xiàn),它具備了區(qū)域感知的能力。
八. Ribbon負載均衡策略
即IRule的實現(xiàn)
IRule實現(xiàn)
- RandomRule: 隨機選擇一個Server。
- RetryRule: 對選定的負載均衡策略機上重試機制,在一個配置時間段內(nèi)當選擇Server不成功,則一直嘗試使用subRule的方式選擇一個可用的server。
- RoundRobinRule: 輪詢選擇, 輪詢index,選擇index對應(yīng)位置的Server。
- AvailabilityFilteringRule: 過濾掉一直連接失敗的被標記為circuit tripped的后端Server,并 過濾掉那些高并發(fā)的后端Server或者使用一個AvailabilityPredicate來包含過濾server的邏輯,其 實就是檢查status里記錄的各個Server的運行狀態(tài)。
- BestAvailableRule: 選擇一個最小的并發(fā)請求的Server,逐個考察Server,如果Server被 tripped了,則跳過。
- WeightedResponseTimeRule: 根據(jù)響應(yīng)時間加權(quán),響應(yīng)時間越長,權(quán)重越小,被選中的可 能性越低。
- ZoneAvoidanceRule: 默認的負載均衡策略,即復(fù)合判斷Server所在區(qū)域的性能和 Server的可用性選擇Server,在沒有區(qū)域的環(huán)境下,類似于輪詢(RandomRule)
- NacosRule: 同集群優(yōu)先調(diào)用
九.自定義負載均衡策略
自定義
public class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {
@Override
public Server choose(Object key) {
.... .... ....
return Server
}
}
全局生效
@Configuration
public class RibbonConfig {
/**
* 全局配置
* 指定負載均衡策略
* @return
*/
@Bean
public IRule() {
//
return new NacosRandomWithWeightRule();
}
}
局部生效
//修改application.yml
# 被調(diào)用的微服務(wù)名
mall‐order:
ribbon:
# 指定使用負載均衡策略
NFLoadBalancerRuleClassName: xxxx.NacosRandomWithWeightRule
十. 饑餓加載
開啟饑餓加載,解決第一次調(diào)用慢的問題
ribbon:
eager‐load:
# 開啟ribbon饑餓加載
enabled: true
# 配置mall‐user使用ribbon饑餓加載,多個使用逗號分隔
clients: mall‐order

