前言
本文為 微服務(wù)負載均衡器Ribbon與LoadBalancer 相關(guān)知識,下邊將對什么是Ribbon
(包括:客戶端的負載均衡
、服務(wù)端的負載均衡
、常見負載均衡算法
),Nacos使用Ribbon
,Ribbon內(nèi)核原理
(包括:Ribbon原理
,Ribbon負載均衡策略
,饑餓加載
),Spring Cloud LoadBalancer
(包括:什么是Spring Cloud LoadBalancer
,RestTemplate整合LoadBalancer
)等進行詳盡介紹~
??博主主頁:小新要變強 的主頁
??Java全棧學習路線可參考:【Java全棧學習路線】最全的Java學習路線及知識清單,Java自學方向指引,內(nèi)含最全Java全棧學習技術(shù)清單~
??算法刷題路線可參考:算法刷題路線總結(jié)與相關(guān)資料分享,內(nèi)含最詳盡的算法刷題路線指南及相關(guān)資料分享~
??Java微服務(wù)開源項目可參考:企業(yè)級Java微服務(wù)開源項目(開源框架,用于學習、畢設(shè)、公司項目、私活等,減少開發(fā)工作,讓您只關(guān)注業(yè)務(wù)!)
??本文上接:Spring Cloud Alibaba全家桶(二)——微服務(wù)組件Nacos注冊中心
目錄
一、什么是Ribbon
目前主流的負載方案分為以下兩種:
- 集中式負載均衡,在消費者和服務(wù)提供方中間使用獨立的代理方式進行負載,有硬件的(比如 F5),也有軟件的(比如Nginx)。
- 客戶端根據(jù)自己的請求情況做負載均衡,Ribbon 就屬于客戶端自己做負載均衡。
Spring Cloud Ribbon是基于Netflix Ribbon 實現(xiàn)的一套客戶端的負載均衡工具,Ribbon客戶端組件提供一系列的完善的配置,如超時,重試等。通過Load Balancer獲取到服務(wù)提供的所有機器實例,Ribbon會自動基于某種規(guī)則(輪詢,隨機)去調(diào)用這些服務(wù)。Ribbon也可以實現(xiàn)我們自己的負載均衡算法。
1??客戶端的負載均衡
例如spring cloud中的ribbon,客戶端會有一個服務(wù)器地址列表,在發(fā)送請求前通過負載均衡算法選擇一個服務(wù)器,然后進行訪問,這是客戶端負載均衡;即在客戶端就進行負載均衡算法分配。
2??服務(wù)端的負載均衡
例如Nginx,通過Nginx進行負載均衡,先發(fā)送請求,然后通過負載均衡算法,在多個服務(wù)器之間選擇一個進行訪問;即在服務(wù)器端再進行負載均衡算法分配。
3??常見負載均衡算法
- 隨機,通過隨機選擇服務(wù)進行執(zhí)行,一般這種方式使用較少;
- 輪訓,負載均衡默認實現(xiàn)方式,請求來之后排隊處理;
- 加權(quán)輪訓,通過對服務(wù)器性能的分型,給高配置,低負載的服務(wù)器分配更高的權(quán)重,均衡各個服務(wù)器的壓力;
- 地址Hash,通過客戶端請求的地址的HASH值取模映射進行服務(wù)器調(diào)度。 ip —>hash
- 最小鏈接數(shù),即使請求均衡了,壓力不一定會均衡,最小連接數(shù)法就是根據(jù)服務(wù)器的情況,比如請求積壓數(shù)等參數(shù),將請求分配到當前壓力最小的服務(wù)器上。
最小活躍數(shù)
二、Nacos使用Ribbon
??(1)引入依賴
nacos-discovery依賴了ribbon,可以不用再引入ribbon依賴。
??(2) 添加@LoadBalanced注解
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
??(3)修改controller
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/findOrderByUserId/{id}")
public R findOrderByUserId(@PathVariable("id") Integer id) {
// RestTemplate調(diào)用
//String url = "http://localhost:8020/order/findOrderByUserId/"+id;
//模擬ribbon實現(xiàn)
//String url = getUri("mall‐order")+"/order/findOrderByUserId/"+id;
// 添加@LoadBalanced
String url = "http://mall‐order/order/findOrderByUserId/"+id;
R result = restTemplate.getForObject(url,R.class);
return result;
}
三、Ribbon內(nèi)核原理
1??Ribbon原理
2??Ribbon負載均衡策略
IRule
這是所有負載均衡策略的父接口,里邊的核心方法就是choose方法,用來選擇一個服務(wù)實例。
AbstractLoadBalancerRule
AbstractLoadBalancerRule是一個抽象類,里邊主要定義了一個ILoadBalancer,這里定義它的目的主要是輔助負責均衡策略選取合適的服務(wù)端實例。
- RandomRule
看名字就知道,這種負載均衡策略就是隨機選擇一個服務(wù)實例,看源碼我們知道,在RandomRule的無參構(gòu)造方法中初始化了一個Random對象,然后在它重寫的choose方法又調(diào)用了choose(ILoadBalancer lb, Object key)這個重載的choose方法,在這個重載的choose方法中,每次利用random對象生成一個不大于服務(wù)實例總數(shù)的隨機數(shù),并將該數(shù)作為下標所以獲取一個服務(wù)實例。
- RoundRobinRule
RoundRobinRule這種負載均衡策略叫做線性輪詢負載均衡策略。這個類的choose(ILoadBalancer lb, Object key)函數(shù)整體邏輯是這樣的:開啟一個計數(shù)器count,在while循環(huán)中遍歷服務(wù)清單,獲取清單之前先通過incrementAndGetModulo方法獲取一個下標,這個下標是一個不斷自增長的數(shù)先加1然后和服務(wù)清單總數(shù)取模之后獲取到的(所以這個下標從來不會越界),拿著下標再去服務(wù)清單列表中取服務(wù),每次循環(huán)計數(shù)器都會加1,如果連續(xù)10次都沒有取到服務(wù),則會報一個警告No available alive servers after 10 tries from load balancer: XXXX。
- RetryRule(在輪詢的基礎(chǔ)上進行重試)
看名字就知道這種負載均衡策略帶有重試功能。首先RetryRule中又定義了一個subRule,它的實現(xiàn)類是RoundRobinRule,然后在RetryRule的choose(ILoadBalancer lb, Object key)方法中,每次還是采用RoundRobinRule中的choose規(guī)則來選擇一個服務(wù)實例,如果選到的實例正常就返回,如果選擇的服務(wù)實例為null或者已經(jīng)失效,則在失效時間deadline之前不斷的進行重試(重試時獲取服務(wù)的策略還是RoundRobinRule中定義的策略),如果超過了deadline還是沒取到則會返回一個null。
- WeightedResponseTimeRule(權(quán)重 —nacos的NacosRule ,Nacos還擴展了一個自己的基于配置的權(quán)重擴展)
WeightedResponseTimeRule是RoundRobinRule的一個子類,在WeightedResponseTimeRule中對RoundRobinRule的功能進行了擴展,WeightedResponseTimeRule中會根據(jù)每一個實例的運行情況來給計算出該實例的一個權(quán)重,然后在挑選實例的時候則根據(jù)權(quán)重進行挑選,這樣能夠?qū)崿F(xiàn)更優(yōu)的實例調(diào)用。WeightedResponseTimeRule中有一個名叫DynamicServerWeightTask的定時任務(wù),默認情況下每隔30秒會計算一次各個服務(wù)實例的權(quán)重,權(quán)重的計算規(guī)則也很簡單,如果一個服務(wù)的平均響應時間越短則權(quán)重越大,那么該服務(wù)實例被選中執(zhí)行任務(wù)的概率也就越大。
- ClientConfigEnabledRoundRobinRule
ClientConfigEnabledRoundRobinRule選擇策略的實現(xiàn)很簡單,內(nèi)部定義了RoundRobinRule,choose方法還是采用了RoundRobinRule的choose方法,所以它的選擇策略和RoundRobinRule的選擇策略一致,不贅述。
- BestAvailableRule
BestAvailableRule繼承自ClientConfigEnabledRoundRobinRule,它在ClientConfigEnabledRoundRobinRule的基礎(chǔ)上主要增加了根據(jù)loadBalancerStats中保存的服務(wù)實例的狀態(tài)信息來過濾掉失效的服務(wù)實例的功能,然后順便找出并發(fā)請求最小的服務(wù)實例來使用。然而loadBalancerStats有可能為null,如果loadBalancerStats為null,則BestAvailableRule將采用它的父類即ClientConfigEnabledRoundRobinRule的服務(wù)選取策略(線性輪詢)。
- ZoneAvoidanceRule (默認規(guī)則,復合判斷server所在區(qū)域的性能和server的可用性選擇服務(wù)器。)
ZoneAvoidanceRule是PredicateBasedRule的一個實現(xiàn)類,只不過這里多一個過濾條件,ZoneAvoidanceRule中的過濾條件是以ZoneAvoidancePredicate為主過濾條件和以AvailabilityPredicate為次過濾條件組成的一個叫做CompositePredicate的組合過濾條件,過濾成功之后,繼續(xù)采用線性輪詢(RoundRobinRule)的方式從過濾結(jié)果中選擇一個出來。
- AvailabilityFilteringRule(先過濾掉故障實例,再選擇并發(fā)較小的實例)
過濾掉一直連接失敗的被標記為circuit tripped的后端Server,并過濾掉那些高并發(fā)的后端Server或者使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就是檢查status里記錄的各個Server的運行狀態(tài)。
??(1)修改默認負載均衡策略
(1)配置類:
@Configuration
public class RibbonConfig {
/**
* 全局配置
* 指定負載均衡策略
* @return
*/
@Bean
public IRule iRule() {
// 指定使用Nacos提供的負載均衡策略(優(yōu)先調(diào)用同一集群的實例,基于隨機權(quán)重)
return new NacosRule();
}
}
注意: 此處有坑。不能寫在@SpringbootApplication注解的@CompentScan掃描得到的地方,否則自定義的配置類就會被所有的RibbonClients共享。 不建議這么使用,推薦yml方式
利用@RibbonClient指定微服務(wù)及其負載均衡策略。
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
//@RibbonClient(name = "mall‐order",configuration = RibbonConfig.class)
//配置多個 RibbonConfig不能被@SpringbootApplication的@CompentScan掃描到,否則就是全局配置的效果
@RibbonClients(value = {
// 在SpringBoot主程序掃描的包外定義配置類
@RibbonClient(name = "mall‐order",configuration = RibbonConfig.class),
@RibbonClient(name = "mall‐account",configuration = RibbonConfig.class)
})
public class MallUserRibbonDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MallUserRibbonDemoApplication.class, args);
}
}
配置文件: 調(diào)用指定微服務(wù)提供的服務(wù)時,使用對應的負載均衡算法
修改application.yml:
# 被調(diào)用的微服務(wù)名
mall‐order:
ribbon:
# 指定使用Nacos提供的負載均衡策略(優(yōu)先調(diào)用同一集群的實例,基于隨機&權(quán)重)
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
??(2)自定義負載均衡策略
通過實現(xiàn) IRule 接口可以自定義負載策略,主要的選擇服務(wù)邏輯在 choose 方法中。
(1)實現(xiàn)基于Nacos權(quán)重的負載均衡策略
@Slf4j
public class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public Server choose(Object key) {
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
String serviceName = loadBalancer.getName();
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
try {
//nacos基于權(quán)重的算法
Instance instance = namingService.selectOneHealthyInstance(serviceName);
return new NacosServer(instance);
} catch (NacosException e) {
log.error("獲取服務(wù)實例異常:{}", e.getMessage());
e.printStackTrace();
}
return null;
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
}
(2)配置自定義的策略
修改application.yml:
# 被調(diào)用的微服務(wù)名
mall‐order:
ribbon:
# 自定義的負載均衡策略(基于隨機&權(quán)重)
NFLoadBalancerRuleClassName: com.tuling.mall.ribbondemo.rule.NacosRandomWithWeightRule
3??饑餓加載
在進行服務(wù)調(diào)用的時候,如果網(wǎng)絡(luò)情況不好,第一次調(diào)用會超時。
Ribbon默認懶加載,意味著只有在發(fā)起調(diào)用的時候才會創(chuàng)建客戶端。
開啟饑餓加載,解決第一次調(diào)用慢的問題:
ribbon:
eager‐load:
# 開啟ribbon饑餓加載
enabled: true
# 配置mall‐user使用ribbon饑餓加載,多個使用逗號分隔
clients: mall‐order
源碼對應屬性配置類:RibbonEagerLoadProperties
測試:
四、Spring Cloud LoadBalancer
1??什么是Spring Cloud LoadBalancer
Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客戶端負載均衡器, 用來替代Ribbon。
Spring官方提供了兩種負載均衡的客戶端:
- RestTemplate: RestTemplate是Spring提供的用于訪問Rest服務(wù)的客戶端,RestTemplate提供了多種便捷訪問遠程Http服務(wù)的方法,能夠大大提高客戶端的編寫效率。默認情況下,RestTemplate默認依賴jdk的HTTP連接工具。
- WebClient: WebClient是從Spring WebFlux 5.0版本開始提供的一個非阻塞的基于響應式編程的進行Http請求的客戶端工具。它的響應式編程的基于Reactor的。WebClient中提供了標準Http請求方式對應的get、post、put、delete等方法,可以用來發(fā)起相應的請求。
2??RestTemplate整合LoadBalancer
??(1)引入依賴
<!‐‐ LoadBalancer ‐‐>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐starter‐loadbalancer</artifactId>
</dependency>
<!‐‐ 提供了RestTemplate支持 ‐‐>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐web</artifactId>
</dependency>
<!‐‐ nacos服務(wù)注冊與發(fā)現(xiàn) 移除ribbon支持‐‐>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring‐cloud‐starter‐alibaba‐nacos‐discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐starter‐netflix‐ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
注意: nacos-discovery中引入了ribbon,需要移除ribbon的包;如果不移除,也可以在yml中配置不使用ribbon。
spring:
application:
name: mall‐user‐loadbalancer‐demo
cloud:
nacos:
discovery:
server‐addr: 127.0.0.1:8848
# 不使用ribbon
loadbalancer:
ribbon:
enabled: false
原理: 默認情況下,如果同時擁有RibbonLoadBalancerClient和BlockingLoadBalancerClient,為了保持向后兼容性,將使用RibbonLoadBalancerClient。要覆蓋它,可以設(shè)置spring.cloud.loadbalancer.ribbon.enabled屬性為false。
??(2)使用@LoadBalanced注解配置RestTemplate
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
??(3)使用
@RestController
@RequestMapping("/user")
public class UserController {
@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;
}
}
后記
文章來源:http://www.zghlxwxcb.cn/news/detail-785724.html
??Java全棧學習路線可參考:【Java全棧學習路線】最全的Java學習路線及知識清單,Java自學方向指引,內(nèi)含最全Java全棧學習技術(shù)清單~
??算法刷題路線可參考:算法刷題路線總結(jié)與相關(guān)資料分享,內(nèi)含最詳盡的算法刷題路線指南及相關(guān)資料分享~文章來源地址http://www.zghlxwxcb.cn/news/detail-785724.html
到了這里,關(guān)于Spring Cloud Alibaba全家桶(三)——微服務(wù)負載均衡器Ribbon與LoadBalancer的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!