Java Spring Cloud 負(fù)載均衡詳解
1. Ribbon 客戶端負(fù)載均衡
1.1 Ribbon 概述
- Ribbon 是 Netflix 提供的一個(gè)基于 HTTP 和 TCP 的客戶端負(fù)載均衡工具。
- Ribbon主要有兩個(gè)功能:
- 簡(jiǎn)化遠(yuǎn)程調(diào)用
- 負(fù)載均衡
客戶端負(fù)載均衡和服務(wù)端負(fù)載均衡的區(qū)別
服務(wù)端負(fù)載均衡
- 負(fù)載均衡算法在服務(wù)端
- 由負(fù)載均衡器維護(hù)服務(wù)地址列表

客戶端負(fù)載均衡
- 負(fù)載均衡算法在客戶端
- 客戶端維護(hù)服務(wù)地址列表

1.2 Ribbon 遠(yuǎn)程調(diào)用
Ribbon 可以簡(jiǎn)化 RestTemplate 的遠(yuǎn)程調(diào)用。
原來(lái)的 Provider 中的遠(yuǎn)程調(diào)用如下:
@GetMapping("/goods/{id}")
public Goods findGoodsById(@PathVariable("id") int id){
//演示discoveryClient 使用
List<ServiceInstance> instances = discoveryClient.getInstances("eureka-provider");
//判斷集合是否有數(shù)據(jù)
if(instances == null || instances.size() == 0){
//集合沒(méi)有數(shù)據(jù)
return null;
}
ServiceInstance instance = instances.get(0);
String host = instance.getHost();//獲取ip
int port = instance.getPort();//獲取端口
System.out.println(host);
System.out.println(port);
String url = "http://"+host+":"+port+"/goods/findOne/"+id;
// 3. 調(diào)用方法
Goods goods = restTemplate.getForObject(url, Goods.class);
return goods;
}
使用 Ribbon 簡(jiǎn)化 restTemplate 調(diào)用:
1.在聲明 restTemplate 的 Bean 時(shí)候,添加一個(gè)注解:@LoadBalanced
@Configuration
public class RestTemplateConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2.在使用 restTemplate 發(fā)起請(qǐng)求時(shí),需要定義 url 時(shí),host:port 可以替換為服務(wù)提供方的應(yīng)用名稱
@GetMapping("/goods2/{id}")
public Goods findGoodsById2(@PathVariable("id") int id){
String url = "http://EUREKA-PROVIDER/goods/findOne/"+id;
// 3. 調(diào)用方法
Goods goods = restTemplate.getForObject(url, Goods.class);
return goods;
}
1.3 Ribbon 負(fù)載均衡
1.既然要負(fù)載均衡,那么我們就需要啟動(dòng)多個(gè) Provider 服務(wù)來(lái)構(gòu)成集群,在啟動(dòng)前先對(duì) Provider 改造一下,讓它將端口號(hào)設(shè)置到商品標(biāo)題上
package com.zt.provider.controller;
/**
* Goods Controller 服務(wù)提供方
*/
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Value("${server.port}")
private int port;
@Autowired
private GoodsService goodsService;
@GetMapping("/findOne/{id}")
public Goods findOne(@PathVariable("id") int id){
Goods goods = goodsService.findOne(id);
goods.setTitle(goods.getTitle() + ":" + port);//將端口號(hào),設(shè)置到商品標(biāo)題上
return goods;
}
}
2.接下來(lái)以多例啟動(dòng) Provider,選擇 edit configurations --> 勾選 allow parallel run


3.然后分別以 8001 和 8002 端口號(hào)分別啟動(dòng) Provider

4.啟動(dòng) Consumer 進(jìn)行測(cè)試
http://localhost:9000/order/goods2/1
采用輪詢的方式,調(diào)用兩個(gè) 8001 和 8002 兩個(gè) Provider
{"id":1,"title":"華為手機(jī):8001","price":3999.0,"count":10000}
{"id":1,"title":"華為手機(jī):8002","price":3999.0,"count":10000}
1.4 Ribbon 負(fù)載均衡策略
| 策略類 | 命名 | 描述 |
|---|---|---|
| RandomRule | 隨機(jī)策略 | 隨機(jī)選擇server |
| RoundRobinRule | 輪詢策略 | 輪詢選擇, 輪詢index,選擇index對(duì)應(yīng)位置的Server; |
| RetryRule | 重試策略 | 對(duì)選定的負(fù)載均衡策略機(jī)上重試機(jī)制,在一個(gè)配置時(shí)間段內(nèi)當(dāng)選擇Server不成功,則一直嘗試使用subRule的方式選擇一個(gè)可用的server; |
| BestAvailableRule | 最低并發(fā)策略 | 逐個(gè)考察server,如果server斷路器打開(kāi),則忽略,再選擇其中并發(fā)鏈接最低的server |
| AvailabilityFilteringRule | 可用過(guò)濾策略 | 過(guò)濾掉一直失敗并被標(biāo)記為circuit tripped的server,過(guò)濾掉那些高并發(fā)鏈接的server(active connections超過(guò)配置的閾值)或者使用一個(gè)AvailabilityPredicate來(lái)包含過(guò)濾server的邏輯,其實(shí)就就是檢查status里記錄的各個(gè)Server的運(yùn)行狀態(tài); |
| ResponseTimeWeightedRule | 響應(yīng)時(shí)間加權(quán)重策略 | 根據(jù)server的響應(yīng)時(shí)間分配權(quán)重,響應(yīng)時(shí)間越長(zhǎng),權(quán)重越低,被選擇到的概率也就越低。響應(yīng)時(shí)間越短,權(quán)重越高,被選中的概率越高,這個(gè)策略很貼切,綜合了各種因素,比如:網(wǎng)絡(luò),磁盤,io等,都直接影響響應(yīng)時(shí)間 |
| ZoneAvoidanceRule | 區(qū)域權(quán)重策略 | 綜合判斷server所在區(qū)域的性能,和server的可用性,輪詢選擇server并且判斷一個(gè)AWS Zone的運(yùn)行性能是否可用,剔除不可用的Zone中的所有server |
設(shè)置負(fù)載均衡策略
1.編碼方式
在 Consumer 服務(wù)編寫(xiě)配置類,采用隨即策略
package com.zt.consumer.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRule {
@Bean
public IRule rule() {
return new RandomRule();
}
}
在啟動(dòng)類上設(shè)置給指定服務(wù)開(kāi)啟負(fù)載均衡策略,比如給 EUREKA-PROVIDER 開(kāi)啟策略 MyRule
package com.zt.consumer;
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
/*
配置Ribbon的負(fù)載均衡策略 name
* name:設(shè)置 服務(wù)提供方的 應(yīng)用名稱
* configuration:設(shè)置負(fù)載均衡Bean
*/
@RibbonClient(name="EUREKA-PROVIDER",configuration = MyRule.class)
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class, args);
}
}
2.配置方式
# 配置的方式設(shè)置Ribbon的負(fù)載均衡策略
EUREKA-PROVIDER: # 設(shè)置的服務(wù)提供方的 應(yīng)用名稱
ribbon:
NFloadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 策略類
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java對(duì)象Serializable接口實(shí)現(xiàn)詳解
這篇文章主要介紹了Java對(duì)象Serializable接口實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
Maven?項(xiàng)目用Assembly打包可執(zhí)行jar包的方法
這篇文章主要介紹了Maven?項(xiàng)目用Assembly打包可執(zhí)行jar包的方法,該方法只可打包非spring項(xiàng)目的可執(zhí)行jar包,需要的朋友可以參考下2023-03-03
Java實(shí)現(xiàn)Promise.all()的示例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)Promise.all()的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
spring-boot-maven-plugin:打包時(shí)排除provided依賴問(wèn)題
這篇文章主要介紹了spring-boot-maven-plugin:打包時(shí)排除provided依賴問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
詳解如何獨(dú)立使用ribbon實(shí)現(xiàn)業(yè)務(wù)客戶端負(fù)載均衡
這篇文章主要為大家介紹了詳解如何獨(dú)立使用ribbon實(shí)現(xiàn)業(yè)務(wù)客戶端負(fù)載均衡,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
java 使用線程監(jiān)控文件目錄變化的實(shí)現(xiàn)方法
這篇文章主要介紹了java 使用線程監(jiān)控文件目錄變化的實(shí)現(xiàn)方法的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-10-10

