一. Ribbon概述
Spring Cloud Ribbon是基于Netflix Ribbon 實現(xiàn)的一套客戶端的負(fù)載均衡工具咽瓷,Ribbon客戶端組件提 供一系列的完善的配置舰讹,如超時,重試等匈睁。通過Load Balancer獲取到服務(wù)提供的所有機器實例桶错, Ribbon會自動基于某種規(guī)則(輪詢,隨機)去調(diào)用這些服務(wù)院刁。Ribbon也可以實現(xiàn)我們自己的負(fù)載均衡算法退腥。
二. 主流負(fù)載均衡
- 集中式負(fù)載均衡
在消費者和服務(wù)提供方中間使用獨立的代理方式進行負(fù)載,有硬件的(比如 F5)享潜,也有軟件的(比如 Nginx)嗅蔬。
- 客戶端負(fù)載均衡
客戶端會有一個服務(wù)器地址列表,在發(fā)送請求前通過負(fù)載均衡算法選擇 一個服務(wù)器艺蝴,然后進行訪問鸟废,這是客戶端負(fù)載均衡。
三. 常見負(fù)載均衡算法
算法就是從服務(wù)列表中按某個規(guī)則選取一個鼠冕。
隨機撇叁,通過隨機選擇服務(wù)進行執(zhí)行,一般這種方式使用較少;
輪訓(xùn)楞捂,負(fù)載均衡默認(rèn)實現(xiàn)方式趋厉,請求來之后排隊處理;
加權(quán)輪訓(xùn)君账,通過對服務(wù)器性能的分型,給高配置椭蹄,低負(fù)載的服務(wù)器分配更高的權(quán)重净赴,均衡各個 服務(wù)器的壓力;
地址Hash玖翅,通過客戶端請求的地址的HASH值取模映射進行服務(wù)器調(diào)度。
最小鏈接數(shù)金度,即使請求均衡了猜极,壓力不一定會均衡,最小連接數(shù)法就是根據(jù)服務(wù)器的情況丢胚,比如請求積壓數(shù)等參數(shù)酬姆,將請求分配到當(dāng)前壓力最小的服務(wù)器上辞色。
服務(wù)每處理一個請求,請求數(shù)+1层亿,處理完-1. 新的請求來時選擇請求數(shù)最少的處理立美。這樣性能最好的服務(wù)器接收最多的請求建蹄。
四. Ribbon 模塊
- ribbon- loadbalancer
負(fù)載均衡模塊,可獨立使用痛单,也可以和別的模塊一起使用劲腿。 Ribbon 內(nèi)置的負(fù)載均衡算法都實現(xiàn)在其中焦人。
- ribbon-eureka
基于 Eureka 封裝的模塊,能夠快速忽匈、方便地集成 Eureka个从。
- ribbon-transport
基于 Netty 實現(xiàn)多協(xié)議的支持,比如 HTTP嫌松、Tcp萎羔、Udp 等碳默。
- ribbon-httpclient
基于 Apache HttpClient 封裝的 REST 客戶端,集成了負(fù)載均衡模塊髓废,可以直接在項目中使用來調(diào)用接口该抒。
- ribbon-example
Ribbon 使用代碼示例,通過這些示例能夠讓你的學(xué)習(xí)事半功倍涌攻。
- ribbon-core
一些比較核心且具有通用性的代碼频伤,客戶端 API 的一些配置和其他 API 的定義憋肖。
五. Ribbon 使用
5.1 直接使用
// 服務(wù)列表
List<Server> serverList = Lists.newArrayList(
new Server("localhost", 8020),
new Server("localhost", 8021));
// 構(gòu)建負(fù)載實例
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 的擴展點婚肆,攔截原本請求后坐慰,利用負(fù)載均衡算法在服務(wù)列表中選出一個服務(wù)结胀,替換服務(wù)名實現(xiàn)負(fù)載均衡調(diào)用的。
@LoadBalanced 原理
1.LoadBalancerAutoConfiguration 自動注入
2.@LoadBalanced利用@Qualifier作為restTemplates注入的篩選條件攀操,篩選出具有負(fù)載均衡標(biāo)識的 RestTemplate速和。
被@LoadBalanced注解的restTemplate會被定制剥汤,添加LoadBalancerInterceptor攔截器。
七. Ribbon 相關(guān)接口
源碼入口RibbonClientConfiguration
- IRule:Ribbon的負(fù)載均衡策略,默認(rèn)采用ZoneAvoidanceRule實現(xiàn)鹿驼,該策略能夠在多區(qū)域環(huán)境下選出 最佳區(qū)域的實例進行訪問畜晰。
- IPing:Ribbon的實例檢查策略,默認(rèn)采用DummyPing實現(xiàn)腊瑟,該檢查策略是一個特殊的實現(xiàn),實際上 它并不會檢查實例是否可用,而是始終返回true河胎,默認(rèn)認(rèn)為所有服務(wù)實例都是可用的虎敦。
- ServerList:服務(wù)實例清單的維護機制,默認(rèn)采用ConfigurationBasedServerList實現(xiàn)胚迫。
- ServerListFilter:服務(wù)實例清單過濾機制唾那,默認(rèn)采ZonePreferenceServerListFilter闹获,該策略能夠優(yōu)先 過濾出與請求方處于同區(qū)域的服務(wù)實例。
- ILoadBalancer:負(fù)載均衡器龟虎,默認(rèn)采用ZoneAwareLoadBalancer實現(xiàn)鲤妥,它具備了區(qū)域感知的能力拱雏。
八. Ribbon負(fù)載均衡策略
即IRule的實現(xiàn)
- RandomRule: 隨機選擇一個Server古涧。
- RetryRule: 對選定的負(fù)載均衡策略機上重試機制,在一個配置時間段內(nèi)當(dāng)選擇Server不成功菇爪,則一直嘗試使用subRule的方式選擇一個可用的server柒昏。
- RoundRobinRule: 輪詢選擇职祷, 輪詢index届囚,選擇index對應(yīng)位置的Server是尖。
- AvailabilityFilteringRule: 過濾掉一直連接失敗的被標(biāo)記為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: 默認(rèn)的負(fù)載均衡策略蚀浆,即復(fù)合判斷Server所在區(qū)域的性能和 Server的可用性選擇Server搜吧,在沒有區(qū)域的環(huán)境下滤奈,類似于輪詢(RandomRule)
- NacosRule: 同集群優(yōu)先調(diào)用
九.自定義負(fù)載均衡策略
自定義
public class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {
@Override
public Server choose(Object key) {
.... .... ....
return Server
}
}
全局生效
@Configuration
public class RibbonConfig {
/**
* 全局配置
* 指定負(fù)載均衡策略
* @return
*/
@Bean
public IRule() {
//
return new NacosRandomWithWeightRule();
}
}
局部生效
//修改application.yml
# 被調(diào)用的微服務(wù)名
mall‐order:
ribbon:
# 指定使用負(fù)載均衡策略
NFLoadBalancerRuleClassName: xxxx.NacosRandomWithWeightRule
十. 饑餓加載
開啟饑餓加載蜒程,解決第一次調(diào)用慢的問題
ribbon:
eager‐load:
# 開啟ribbon饑餓加載
enabled: true
# 配置mall‐user使用ribbon饑餓加載伺帘,多個使用逗號分隔
clients: mall‐order