Ribbon是Netflix公司開(kāi)源的一個(gè)負(fù)載均衡的項(xiàng)目(https://github.com/Netflix/ribbon),它是一個(gè)基于HTTP、TCP的客戶(hù)端負(fù)載均衡器。
服務(wù)端負(fù)載均衡
負(fù)載均衡是微服務(wù)架構(gòu)中必須使用的技術(shù)羊壹,通過(guò)負(fù)載均衡來(lái)實(shí)現(xiàn)系統(tǒng)的高可用核无、集群擴(kuò)容等功能。負(fù)載均衡可通過(guò)硬件設(shè)備及軟件來(lái)實(shí)現(xiàn)汞舱,硬件比如:F5、Array等宗雇,軟件比如:LVS昂芜、Nginx等。
用戶(hù)請(qǐng)求先到達(dá)負(fù)載均衡器(也相當(dāng)于一個(gè)服務(wù))赔蒲,負(fù)載均衡器根據(jù)負(fù)載均衡算法將請(qǐng)求轉(zhuǎn)發(fā)到微服務(wù)泌神。負(fù)載均衡算法有:輪訓(xùn)、隨機(jī)舞虱、加權(quán)輪訓(xùn)欢际、加權(quán)隨機(jī)、地址哈希等方法矾兜,負(fù)載均衡器維護(hù)一份服務(wù)列表损趋,根據(jù)負(fù)載均衡算法將請(qǐng)求轉(zhuǎn)發(fā)到相應(yīng)的微服務(wù)上,所以負(fù)載均衡可以為微服務(wù)集群分擔(dān)請(qǐng)求椅寺,降低系統(tǒng)的壓力
客戶(hù)端負(fù)載均衡
上圖是服務(wù)端負(fù)載均衡舶沿,客戶(hù)端負(fù)載均衡與服務(wù)端負(fù)載均衡的區(qū)別在于客戶(hù)端要維護(hù)一份服務(wù)列表,Ribbon從Eureka Server獲取服務(wù)列表配并,Ribbon根據(jù)負(fù)載均衡算法直接請(qǐng)求到具體的微服務(wù)括荡,中間省去了負(fù)載均衡服務(wù)。
Ribbon負(fù)載均衡的流程圖:
在消費(fèi)微服務(wù)中使用Ribbon實(shí)現(xiàn)負(fù)載均衡溉旋,Ribbon先從Eureka Server 或 Nacos Server中獲取服務(wù)列表畸冲。
Ribbon根據(jù)負(fù)載均衡的算法去調(diào)用微服務(wù)。
Ribbon測(cè)試
Spring Cloud引入Ribbon配合 restTemplate 實(shí)現(xiàn)客戶(hù)端負(fù)載均衡。Java中遠(yuǎn)程調(diào)用的技術(shù)有很多邑闲,如:webservice算行、socket、rmi苫耸、Apache HttpClient州邢、OkHttp等。
- 在客戶(hù)端添加Ribbon依賴(lài)
注意:由于我們之前整合Nacos時(shí)引入了spring-cloud-starter-alibaba-nacos-discovery
這個(gè)依賴(lài)包褪子,而這個(gè)包默認(rèn)已經(jīng)幫我們繼承了Ribbon量淌,所有這里可以不用單獨(dú)引入Ribbon依賴(lài)包。
- 配置Ribbon參數(shù)
ribbon:
MaxAutoRetries: 2 #最大重試次數(shù)嫌褪,當(dāng)Eureka中可以找到服務(wù)呀枢,但是服務(wù)連不上時(shí)將會(huì)重試
MaxAutoRetriesNextServer: 3 #切換實(shí)例的重試次數(shù)
OkToRetryOnAllOperations: false #對(duì)所有操作請(qǐng)求都進(jìn)行重試,如果是get則可以笼痛,如果是post裙秋,put等操作沒(méi)有實(shí)現(xiàn)冪等的情況下是很危險(xiǎn)的,所以設(shè)置為false
ConnectTimeout: 5000 #請(qǐng)求連接的超時(shí)時(shí)間
ReadTimeout: 6000 #請(qǐng)求處理的超時(shí)時(shí)間
- 負(fù)載均衡測(cè)試
啟動(dòng)兩個(gè)服務(wù),端口需要不一致
定義RestTemplate缨伊,使用@LoadBalanced注解
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
測(cè)試代碼
@Slf4j
@RestController
public class TestController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/test")
public String test() {
String result = restTemplate.getForObject("http://alibaba-nacos-discovery-server/hello?name=wolf", String.class);
return "Return : " + result;
}
}
可以看到摘刑,在定義RestTemplate
時(shí)候,增加了@LoadBalanced
注解刻坊,而在真正調(diào)用服務(wù)接口的時(shí)候枷恕,原來(lái)host部分是通過(guò)手工拼接ip和端口形式。而這里直接采用服務(wù)名來(lái)寫(xiě)請(qǐng)求路徑即可紧唱。在真正調(diào)用的時(shí)候活尊,Spring Cloud會(huì)將請(qǐng)求攔截下來(lái)隶校,然后通過(guò)Ribbon從Nacos Server獲取服務(wù)列表漏益,并通過(guò)負(fù)載均衡器選出節(jié)點(diǎn),并替換服務(wù)名部分為具體的ip和端口深胳,交給RestTemplate去請(qǐng)求绰疤,從而實(shí)現(xiàn)基于服務(wù)名的負(fù)載均衡調(diào)用。
Ribbon饑餓加載
默認(rèn)情況下Ribbon是懶加載的舞终。當(dāng)服務(wù)起動(dòng)好之后轻庆,第一次請(qǐng)求是非常慢的,第二次之后就快很多敛劝。
解決方式:開(kāi)啟饑餓加載
ribbon:
eager-load:
enabled: true #開(kāi)啟饑餓加載
clients: server-1,server-2,server-3 #為哪些服務(wù)的名稱(chēng)開(kāi)啟饑餓加載,多個(gè)用逗號(hào)分隔
Ribbon組件
接口 | 作用 | 默認(rèn)值 |
---|---|---|
IclientConfig | 讀取配置 | DefaultClientConfigImpl |
IRule | 負(fù)載均衡規(guī)則余爆,選擇實(shí)例 | ZoneAvoidanceRule |
IPing | 篩選掉ping不通的實(shí)例 | DummyPing(該類(lèi)什么不干,認(rèn)為每個(gè)實(shí)例都可用夸盟,都能ping通) |
ServerList<Server> | 交給Ribbon的實(shí)例列表 | Ribbon:ConfigurationBasedServerList Spring Cloud Alibaba:NacosServerList |
ServerListFilter<Server> | 過(guò)濾掉不符合條件的實(shí)例 | ZonePreferenceServerListFilter |
ILoadBalancer | Ribbon的入口 | ZoneAwareLoadBalancer |
ServerListUpdater | 更新交給Ribbon的List的策略 | PollingServerListUpdater |
這里的每一項(xiàng)都可以自定義:
IclientConfig
Ribbon支持非常靈活的配置就是有該組件提供的
IRule
為Ribbon提供規(guī)則蛾方,從而選擇實(shí)例、該組件是最核心組件
舉例:
- 代碼方式:
@Configuration
public class RibbonRuleConfig {
@Bean
public IRule ribbonRulr() {
return new RandomRule();
}
@Bean
public IPing iPing(){
return new PingUrl();
}
}
- 配置屬性方式:
<clientName>:
ribbon:
NFLoadBalancerClassName: #ILoadBalancer該接口實(shí)現(xiàn)類(lèi)
NFLoadBalancerRuleClassName: #IRule該接口實(shí)現(xiàn)類(lèi)
NFLoadBalancerPingClassName: #Iping該接口實(shí)現(xiàn)類(lèi)
NIWSServerListClassName: #ServerList該接口實(shí)現(xiàn)類(lèi)
NIWSServerListFilterClassName: #ServiceListFilter該接口實(shí)現(xiàn)類(lèi)
在這些屬性中定義的類(lèi)優(yōu)先于使用@RibbonClient(configuration=RibbonConfig.class)Spring 定義的bean 以及由Spring Cloud Netflix提供的默認(rèn)值。描述:配置文件中定義ribbon優(yōu)先代碼定義
Ribbon負(fù)載均衡的八種算法桩砰,其中ResponseTimeWeightedRule已廢除
規(guī)則名稱(chēng) | 特點(diǎn) |
---|---|
AvailabilityFilteringRule | 過(guò)濾掉一直連接失敗的被標(biāo)記為circuit tripped(電路跳閘)的后端Service拓春,并過(guò)濾掉那些高并發(fā)的后端Server或者使用一個(gè)AvailabilityPredicate來(lái)包含過(guò)濾Server的邏輯,其實(shí)就是檢查status的記錄的各個(gè)Server的運(yùn)行狀態(tài) |
BestAvailableRule | 選擇一個(gè)最小的并發(fā)請(qǐng)求的Server亚隅,逐個(gè)考察Server硼莽,如果Server被tripped了,則跳過(guò) |
RandomRule | 隨機(jī)選擇一個(gè)Server |
ResponseTimeWeightedRule | 已廢棄煮纵,作用同WeightedResponseTimeRule |
RetryRule | 對(duì)選定的負(fù)責(zé)均衡策略機(jī)上充值機(jī)制懂鸵,在一個(gè)配置時(shí)間段內(nèi)當(dāng)選擇Server不成功,則一直嘗試使用subRule的方式選擇一個(gè)可用的Server |
RoundRobinRule | 輪詢(xún)選擇醉途,輪詢(xún)index矾瑰,選擇index對(duì)應(yīng)位置Server |
WeightedResponseTimeRule | 根據(jù)相應(yīng)時(shí)間加權(quán),相應(yīng)時(shí)間越長(zhǎng)隘擎,權(quán)重越小殴穴,被選中的可能性越低 |
ZoneAvoidanceRule |
(默認(rèn)是這個(gè)) 負(fù)責(zé)判斷Server所Zone的性能和Server的可用性選擇Server,在沒(méi)有Zone的環(huán)境下货葬,類(lèi)似于輪詢(xún)(RoundRobinRule) |
實(shí)現(xiàn)負(fù)載均衡<細(xì)粒度>配置-隨機(jī)
- 方式一:代碼方式
首先定義RestTemplate采幌,并且添加注解@LoadBalanced,這樣RestTemplate就實(shí)現(xiàn)了負(fù)載均衡
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
//template.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));//解決中文亂碼
return new RestTemplate();
}
在SpringBootApplication主類(lèi)下添加配置類(lèi)震桶。該類(lèi)主要作用于為哪個(gè)服務(wù)做負(fù)載均衡休傍。默認(rèn)的是輪訓(xùn)
@Configuration
@RibbonClient(name = "${服務(wù)名稱(chēng)}", configuration = GoodsRibbonRuleConfig.class)//configuration: 指向負(fù)載均衡規(guī)則的配置類(lèi)
public class GoodsRibbonConfig {
}
添加Ribbon的配置類(lèi),注意該類(lèi)必須配置在@SpringBootApplication主類(lèi)以外的包下
蹲姐。不然的話(huà)所有的服務(wù)都會(huì)按照這個(gè)規(guī)則來(lái)實(shí)現(xiàn)磨取。會(huì)被所有的RibbonClient共享。主要是主類(lèi)的主上下文和Ribbon的子上下文起沖突了柴墩。父子上下文不能重疊
@Configuration
public class GoodsRibbonRuleConfig {
@Bean
public IRule ribbonRulr() {
return new RandomRule();
}
}
- 方式二:配置屬性方式
server-1: # 服務(wù)名稱(chēng) Service-ID
ribbon:
# 屬性配置方式【推薦】
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 配置文件配置負(fù)載均衡算法-我這里使用的是自定義的Ribbon的負(fù)載均衡算法忙厌,默認(rèn)
優(yōu)先級(jí):配置(不會(huì)影響其他服務(wù))>(大于) 硬編碼(類(lèi)得寫(xiě)在SpringBoot啟動(dòng)類(lèi)包外,不然會(huì)影響其他服務(wù))
總結(jié):
配置方式 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|
代碼配置 | 基于代碼江咳,更加靈活 | 有坑(父子上下文) 線(xiàn)上修改得重新打包逢净,發(fā)布 |
屬性配置 | 易上手 | 配置更加直觀 線(xiàn)上修改無(wú)需重新打包,發(fā)布 優(yōu)先級(jí)更高 極端場(chǎng)景下沒(méi)有配置配置方式靈活 |
實(shí)現(xiàn)負(fù)載均衡<全局>配置-隨機(jī)
- 方式一:Ribbon的配置類(lèi)定義在主類(lèi)下
讓ComponentScan上下文重疊(強(qiáng)烈不建議使用) - 方式二:
@Configuration
@RibbonClients(defaultConfiguration = GoodsRibbonRuleConfig.class)//Ribbon負(fù)載均衡全局粒度配置(所有服務(wù)都按照這個(gè)配置)
public class RibbonConfig {
}
擴(kuò)展Ribbon-支持Nacos權(quán)重
默認(rèn)情況下Ribbon是不支持Nacos的權(quán)重負(fù)載均衡選擇的歼指,這里我們自己擴(kuò)展一個(gè)Rule爹土,然Ribbon支持Nacos的權(quán)重規(guī)則。
- 創(chuàng)建NacosWeightedRule類(lèi)
package com.thtf.contentcenter.configuration;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;
@Slf4j
public class NacosWeightedRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
//讀取配置文件踩身,并初始化
}
@Override
public Server choose(Object o) {
try {
BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
//想要請(qǐng)求的微服務(wù)名稱(chēng)
String name = loadBalancer.getName();
//實(shí)現(xiàn)負(fù)載均衡算法
//拿到服務(wù)發(fā)現(xiàn)相關(guān)API
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
//nacos client自動(dòng)通過(guò)基于權(quán)重的負(fù)載均衡算法胀茵,給我們選擇一個(gè)實(shí)例。
Instance instance = namingService.selectOneHealthyInstance(name);
log.info("選擇的實(shí)例是:port = {}, instance = {}", instance.getPort(), instance);
return new NacosServer(instance);
} catch (NacosException e) {
log.error("選擇實(shí)例異常:{}", e.getMessage(), e);
return null;
}
}
}
- 創(chuàng)建RibbonConfiguration類(lèi)
package com.thtf.contentcenter.ribbonconfiguration;
import com.istimeless.contentcenter.configuration.NacosWeightedRule;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
return new NacosWeightedRule();
}
}
特別注意:RibbonConfiguration要建在啟動(dòng)類(lèi)掃描不到的地方挟阻,如圖所示:
- 創(chuàng)建UserCenterRibbonConfiguration類(lèi)琼娘,實(shí)現(xiàn)全局配置
package com.thtf.contentcenter.configuration;
import com.istimeless.ribbonconfiguration.RibbonConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Configuration;
@Configuration
@RibbonClients(defaultConfiguration = RibbonConfiguration.class)
public class UserCenterRibbonConfiguration {
}
擴(kuò)展Ribbon-同集群優(yōu)先
在Nacos上呵哨,支持集群配置。集群是指對(duì)指定微服務(wù)的一種虛擬分類(lèi)轨奄。集群還是比較有用的孟害,例如:
- 為了容災(zāi),把指定微服務(wù)同時(shí)部署在兩個(gè)機(jī)房(例如同城多活挪拟,其中1個(gè)機(jī)房崩潰了挨务,另一個(gè)機(jī)房還能頂上,異地多活防止自然災(zāi)害)
- 調(diào)用時(shí)玉组,可優(yōu)先調(diào)用同機(jī)房的實(shí)例谎柄,如果同機(jī)房沒(méi)有實(shí)例,再跨機(jī)房調(diào)用惯雳。
雖然Spring Cloud Alibaba支持集群配置朝巫,例如:
spring:
cloud:
nacos:
discovery:
# 北京機(jī)房集群
cluster-name: BJ
但在調(diào)用時(shí),服務(wù)消費(fèi)者并不會(huì)優(yōu)先調(diào)用同集群的實(shí)例石景。
本節(jié)來(lái)探討如何擴(kuò)展Ribbon劈猿,從而實(shí)現(xiàn)同集群優(yōu)先調(diào)用的效果,并且還能支持Nacos權(quán)重配置潮孽。關(guān)于權(quán)重配置揪荣,前面已經(jīng)實(shí)現(xiàn)了,在前面的基礎(chǔ)上實(shí)現(xiàn)同集群優(yōu)先策略往史。
/**
* 支持優(yōu)先調(diào)用同集群實(shí)例的ribbon負(fù)載均衡規(guī)則.
*
* @author itmuch.com
*/
@Slf4j
public class NacosRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public Server choose(Object key) {
try {
String clusterName = this.nacosDiscoveryProperties.getClusterName();
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
String name = loadBalancer.getName();
NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance();
// 1. 找到指定服務(wù)的所有實(shí)例 A
List<Instance> instances = namingService.selectInstances(name, true);
if (CollectionUtils.isEmpty(instances)) {
return null;
}
List<Instance> instancesToChoose = instances;
if (StringUtils.isNotBlank(clusterName)) {
// 2. 過(guò)濾出相同集群下的所有實(shí)例 B
List<Instance> sameClusterInstances = instances.stream()
.filter(instance -> Objects.equals(clusterName, instance.getClusterName()))
.collect(Collectors.toList());
// 3. 如果B為空仗颈,就用A
if (!CollectionUtils.isEmpty(sameClusterInstances)) {
instancesToChoose = sameClusterInstances;
} else {
log.warn("發(fā)生跨集群的調(diào)用,name = {}, clusterName = {}, instance = {}", name, clusterName, instances);
}
}
// 4. 基于權(quán)重的負(fù)載均衡算法椎例,返回一個(gè)實(shí)例
Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToChoose);
return new NacosServer(instance);
} catch (Exception e) {
log.warn("NacosRule發(fā)生異常", e);
return null;
}
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
}
負(fù)載均衡算法:
// Balancer來(lái)自于com.alibaba.nacos.client.naming.core.Balancer挨决,也就是Nacos Client自帶的基于權(quán)重的負(fù)載均衡算法。
public class ExtendBalancer extends Balancer {
/**
* 根據(jù)權(quán)重订歪,隨機(jī)選擇實(shí)例
*
* @param instances 實(shí)例列表
* @return 選擇的實(shí)例
*/
public static Instance getHostByRandomWeight2(List<Instance> instances) {
return getHostByRandomWeight(instances);
}
}
配置:
microservice-provider-user:
ribbon:
NFLoadBalancerRuleClassName: com.itmuch.cloud.study.ribbon.NacosClusterAwareWeightedRule
這樣脖祈,服務(wù)在調(diào)用microservice-provider-user 這個(gè)服務(wù)時(shí),就會(huì)優(yōu)先選擇相同集群下的實(shí)例陌粹。
擴(kuò)展Ribbon-基于元數(shù)據(jù)的版本控制
至此撒犀,已經(jīng)實(shí)現(xiàn)了
- 優(yōu)先調(diào)用同集群下的實(shí)例
- 實(shí)現(xiàn)基于權(quán)重配置的負(fù)載均衡
但實(shí)際項(xiàng)目福压,我們可能還會(huì)有這樣的需求:
一個(gè)微服務(wù)在線(xiàn)上可能多版本共存掏秩,例如: - 服務(wù)提供者有兩個(gè)版本:v1、v2
- 服務(wù)消費(fèi)者也有兩個(gè)版本:v1荆姆、v2
v1/v2是不兼容的蒙幻。服務(wù)消費(fèi)者v1只能調(diào)用服務(wù)提供者v1;消費(fèi)者v2只能調(diào)用提供者v2胆筒。如何實(shí)現(xiàn)呢邮破?
下面圍繞該場(chǎng)景诈豌,實(shí)現(xiàn)微服務(wù)之間的版本控制。
元數(shù)據(jù)
元數(shù)據(jù)就是一堆的描述信息抒和,以map存儲(chǔ)矫渔。舉個(gè)例子:
spring:
cloud:
nacos:
metadata:
# 自己這個(gè)實(shí)例的版本
version: v1
# 允許調(diào)用的提供者版本
target-version: v1
需求分析
我們需要實(shí)現(xiàn)的有兩點(diǎn):
- 優(yōu)先選擇同集群下,符合metadata的實(shí)例
- 如果同集群加沒(méi)有符合metadata的實(shí)例摧莽,就選擇所有集群下庙洼,符合metadata的實(shí)例
代碼實(shí)現(xiàn)
@Slf4j
public class NacosFinalRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public Server choose(Object key) {
// 負(fù)載均衡規(guī)則:優(yōu)先選擇同集群下,符合metadata的實(shí)例
// 如果沒(méi)有镊辕,就選擇所有集群下油够,符合metadata的實(shí)例
// 1. 查詢(xún)所有實(shí)例 A
// 2. 篩選元數(shù)據(jù)匹配的實(shí)例 B
// 3. 篩選出同cluster下元數(shù)據(jù)匹配的實(shí)例 C
// 4. 如果C為空,就用B
// 5. 隨機(jī)選擇實(shí)例
try {
String clusterName = this.nacosDiscoveryProperties.getClusterName();
String targetVersion = this.nacosDiscoveryProperties.getMetadata().get("target-version");
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
String name = loadBalancer.getName();
NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance();
// 所有實(shí)例
List<Instance> instances = namingService.selectInstances(name, true);
List<Instance> metadataMatchInstances = instances;
// 如果配置了版本映射征懈,那么只調(diào)用元數(shù)據(jù)匹配的實(shí)例
if (StringUtils.isNotBlank(targetVersion)) {
metadataMatchInstances = instances.stream()
.filter(instance -> Objects.equals(targetVersion, instance.getMetadata().get("version")))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(metadataMatchInstances)) {
log.warn("未找到元數(shù)據(jù)匹配的目標(biāo)實(shí)例石咬!請(qǐng)檢查配置。targetVersion = {}, instance = {}", targetVersion, instances);
return null;
}
}
List<Instance> clusterMetadataMatchInstances = metadataMatchInstances;
// 如果配置了集群名稱(chēng)卖哎,需篩選同集群下元數(shù)據(jù)匹配的實(shí)例
if (StringUtils.isNotBlank(clusterName)) {
clusterMetadataMatchInstances = metadataMatchInstances.stream()
.filter(instance -> Objects.equals(clusterName, instance.getClusterName()))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(clusterMetadataMatchInstances)) {
clusterMetadataMatchInstances = metadataMatchInstances;
log.warn("發(fā)生跨集群調(diào)用鬼悠。clusterName = {}, targetVersion = {}, clusterMetadataMatchInstances = {}", clusterName, targetVersion, clusterMetadataMatchInstances);
}
}
Instance instance = ExtendBalancer.getHostByRandomWeight2(clusterMetadataMatchInstances);
return new NacosServer(instance);
} catch (Exception e) {
log.warn("發(fā)生異常", e);
return null;
}
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
}
** 負(fù)載均衡算法:**
public class ExtendBalancer extends Balancer {
/**
* 根據(jù)權(quán)重,隨機(jī)選擇實(shí)例
*
* @param instances 實(shí)例列表
* @return 選擇的實(shí)例
*/
public static Instance getHostByRandomWeight2(List<Instance> instances) {
return getHostByRandomWeight(instances);
}
}
思考
截止到這里亏娜,我們已經(jīng)對(duì)Ribbon的基本使用已經(jīng)如何自定義Ribbon負(fù)載均衡規(guī)則做了詳細(xì)說(shuō)明厦章,但細(xì)心的人會(huì)發(fā)現(xiàn),我使用上面 RestTemplate 地址拼接方式調(diào)用服務(wù)接口會(huì)存在以下幾點(diǎn)不足:
- 代碼可讀性差
- 復(fù)雜的url接口地址難以維護(hù)
- 編碼體驗(yàn)不統(tǒng)一
帶著這些不足照藻,我們引入下一章要講解的另一種服務(wù)調(diào)用方式:Feign