目錄
前言
Ribbon
是一個Netflix
開源的客戶端側負載均衡器,其提供了豐富的負載均衡算法,服務消費者集成Ribbon
后,Ribbon
會自動從Nacos Server
獲取想要調用的服務的地址列表,通過負載均衡算法計算出一個實例交給RestTemplate
調用
注:Spring Cloud 2020 已移除對 Ribbon 的支持,相應的,Spring Cloud 2021 版本 Nacos 中 也刪除了Ribbon 的 jar 包,實現時需要注意版本依賴關系
環境
Spring Cloud Hoxton.SR9 + Spring Cloud Alibaba 2.2.6.RELEASE
簡單示例
spring-cloud-starter-alibaba-nacos-discovery
中默認包含Ribbon
,所以不需要添加依賴
這里的示例代碼是內容中心(content-center)通過調用用戶中心(user-center)的兩個實例看是否實現負載均衡
user-center
TestController.java
@RestController
@Slf4j
public class TestController {
@GetMapping("/test/{name}")
public String test(@PathVariable String name) {
log.info("請求...");
return "hello " + name;
}
}
- 用戶中心以
8081
,8082
端口啟動
content-center
- 啟動類
/**
* @LoadBalanced 為RestTemplate 整合Ribbon
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
TestController.java
@RestController
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TestController {
private final RestTemplate restTemplate;
/**
* 整合Ribbon
* @return
*/
@GetMapping("test3")
public String test3() {
/**
* RestTemplate 請求時,ribbon會把user-center轉換成用戶中心在Nacos上的地址,
* 進行負載均衡算法計算出一個實例去請求
*/
return restTemplate.getForObject(
"http://user-center/test/{name}",
String.class,
"Coisini"
);
}
}
測試
- 訪問接口測試,可以發現
Ribbon
以輪詢的方式實現負載均衡
Ribbon 的組成和默認的負載均衡規則
Ribbon 的組成
Ribbon
為所有的組件提供了接口,如果對默認值不滿意,可以實現這些接口進行二次開發
接口 | 作用 | 默認值 |
---|---|---|
IClientConfig | 讀取配置 | DefaultClientConfigImpl |
IRule | 負載均衡規則,選擇實例 | ZoneAvoidanceRule |
IPing | 篩選掉ping不通的實例 | DummyPing |
ServerList< Server> | 交給Ribbon的實例列表 | Ribbon:ConfigurationBasedServerList Spring Cloud Alibaba: NacosServerList |
ServerListFilter< Server> | 過濾掉不符合條件的實例 | ZonePreferenceServerListFilter |
ILoadBalancer | Ribbon的入口 | ZoneAwareLoadBalancer |
ServerListUpdater | 更新交給Ribbon的List的策略 | PollingServerListUpdater |
Ribbon 默認的負載均衡規則
Ribbon
默認的負載均衡規則是ZoneAvoidanceRule
,在沒有zone
的情況下默認是輪詢Ribbon
內置的負載均衡規則如下
規則名稱 | 特點 |
---|---|
AvailabilityFilteringRule | 過濾掉一直連接失敗的被標記為circuit tripped的后端Server,並過濾掉那些高並發的后端Server或者使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就是檢查status里記錄的各個Server的運行狀態 |
BestAvailableRule | 選擇一個最小的並發請求的Server,逐個考察Server,如果Server被tripped了,則跳過 |
RandomRule | 隨機選擇一個Server |
ResponseTimeWeightedRule | 已廢棄,作用同WeightedResponseTimeRule |
RetryRule | 對選定的負載均衡策略機上重試機制,在同一個配置時間段內當選擇Server不成功,則一直嘗試使用subRule的方式選擇一個可用的Server |
RoundRobinRule | 輪詢選擇,輪詢index,選擇index對應位置的Server |
WeightedResponseTimeRule | 根據響應時間加權,響應時間越長,權重越小,被選中的可能性越低 |
ZoneAvoidanceRule | 復合判斷Server所在Zone的性能和Server的可用性選擇Server,在沒有Zone的環境下,類似於輪詢(RoundRobinRule) |
Ribbon 的自定義配置
實現目的:通過自定義配置實現隨機選擇
Java 代碼配置方式
UserCenterRibbonConfiguration.java
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Configuration;
import ribbonconfiguration.RibbonConfiguration;
/**
* @Description 用戶中心配置類
*/
@Configuration
@RibbonClient(name = "user-center", configuration = RibbonConfiguration.class)
public class UserCenterRibbonConfiguration {
}
RibbonConfiguration.java
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description Ribbon的配置類
* Ribbon的配置類要有@Configuration注解,但不能被@ComponentScan重復掃描
* 否則就會被所有的RibbonClient共享
*/
@Configuration
public class RibbonConfiguration {
/**
* 自定義負載均衡規則
* RandomRule 隨機選擇
* @return
*/
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
}
- 目錄結構如下所示,
Ribbon
配置類RibbonConfiguration.java
位置在java
目錄下,其作用是避免父子上下文重疊,Ribbon
的配置類要有@Configuration
注解,但不能被@ComponentScan
重復掃描,否則就會被所有的RibbonClient
共享
- 接口訪問測試發現隨機訪問已實現
yml 屬性配置方式
- 注釋
Java
代碼配置方式中的代碼,在application.yml
中添加user-center
的負載均衡規則,也能實現相同的效果
user-center:
ribbon:
# Ribbon負載均衡規則的全路徑
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
Ribbon 的全局配置
- 有自定義配置就有全局配置,可以通過修改
@RibbonClient
注解為@RibbonClients
注解實現全局配置 UserCenterRibbonConfiguration.java
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Configuration;
import ribbonconfiguration.RibbonConfiguration;
/**
* @Description 用戶中心配置類
*/
@Configuration
@RibbonClients(defaultConfiguration = RibbonConfiguration.class)
public class UserCenterRibbonConfiguration {
}
RibbonConfiguration.java
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description Ribbon的配置類
*/
@Configuration
public class RibbonConfiguration {
/**
* 自定義負載均衡規則
* RandomRule 隨機選擇
* @return
*/
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
}
Ribbon 的飢餓加載
-
默認情況下
Ribbon
是懶加載的,當RestTemplate
第一次調用RibbonClient
時才會創建一個client
,這樣會導致首次請求過慢或失敗的問題,可以通過屬性配置開啟Ribbon
的飢餓加載 -
application.yml
ribbon:
eager-load:
# 開啟飢餓加載
enabled: true
# 為哪些RibbonClient開啟飢餓加載,多個用 "," 隔開
clients: user-center
項目源碼
GitHub
: https://github.com/Maggieq8324/coisini-cloud-alibabaGitee
: https://gitee.com/maggieq8324/coisini-cloud-alibaba
