- Spring Cloud Ribbon是一個基于http和tcp的客戶端負(fù)載均衡器,是基于Netflix Ribbon實(shí)現(xiàn)的。在微服務(wù)架構(gòu)中,業(yè)務(wù)都會被拆分成一個獨(dú)立的服務(wù),服務(wù)與服務(wù)的通訊是基于http Restful的。Spring Cloud有兩種服務(wù)調(diào)用方式,一種是ribbon+restTemplate,另一種是feign。
- Ribbon是一個服務(wù)調(diào)用組件,并且是一個客戶端實(shí)現(xiàn)負(fù)載均衡的處理的組件。
一、客戶單負(fù)載均衡和服務(wù)端負(fù)載均衡
1、服務(wù)端負(fù)載均衡
-
通常我們說的負(fù)載均衡是指服務(wù)端負(fù)載均衡,包括軟件負(fù)載均衡和硬件負(fù)載均衡。常用服務(wù)端負(fù)載均衡架構(gòu):
服務(wù)端服務(wù)均衡架構(gòu)圖 - 在服務(wù)端負(fù)載均衡中,會通過某種手段維護(hù)一份可用的服務(wù)端清單,然后通過心跳檢查的機(jī)制來剔除失效不可用的服務(wù)端節(jié)點(diǎn)。當(dāng)客戶端發(fā)送請求到負(fù)載均衡器時候,負(fù)載均衡器會按某種負(fù)載均衡算法從維護(hù)的可用服務(wù)器清單中取出一臺服務(wù)器的地址,進(jìn)行轉(zhuǎn)發(fā)。
2、客戶端負(fù)載均衡
-
客戶端負(fù)載均衡和服務(wù)端負(fù)載均衡最大的區(qū)別在于服務(wù)清單所存儲的位置。在客戶端負(fù)載均衡中,所有的客戶端節(jié)點(diǎn)都有一份自己要訪問的服務(wù)端清單,這些清單統(tǒng)統(tǒng)都是從服務(wù)注冊中心(比如eureka)獲取的。
Ribbon客戶端負(fù)載均衡架構(gòu)圖 - 在微服務(wù)架構(gòu)中使用Ribbon作為客戶端負(fù)載均衡調(diào)用步驟
1、服務(wù)提供者,啟動多個應(yīng)用實(shí)例并注冊到 注冊中心
2、服務(wù)消費(fèi)者直接通過調(diào)用被@LoaderBalance注解修飾過的RestTemplate來實(shí)現(xiàn)服務(wù)接口的調(diào)用。
二、RestTemplate詳解
- RestTemplate是一個http請求的客戶端工具,它不是類似HttpClient的東東,也不是類似Jackson,jaxb等工具,但它封裝了這些工具.RestTemplate是Spring 調(diào)用http的client端核心類.顧名思義,與其它template類如JdbcTemplate一樣,它封裝了與http server的通信的細(xì)節(jié),使調(diào)用端無須關(guān)心http接口響應(yīng)的消息是什么格式,統(tǒng)統(tǒng)使用Java pojo來接收請求結(jié)果.它主要做了以下事情:
封裝并屏蔽了http通信細(xì)節(jié)
組裝Http請求參數(shù)
抽取結(jié)果并轉(zhuǎn)成調(diào)用端指定的Java pojo對象
屏蔽了不同消息格式的差異化處理
- 在http通信的底層,它默認(rèn)采用的是Jdk的標(biāo)準(zhǔn)設(shè)施,當(dāng)然你也可以切換成其它的http類庫 例如ApacheHttpComponents,Netty, andOkHttp等.,RestTemplate這個類是用在同步調(diào)用上的,異步調(diào)用請移步AsyncRestTemplate
1、Restful API
(1)get
api:
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType)
//返回String對象
ResponseEntity<String> strResults = restTemplate.getForEntity("domain/user?name={1}",
String.class, "qiu");
// Map<String,Object> params=new HashMap<>();
// params.put("name","qiu" );
// ResponseEntity<String> strResults = restTemplate.getForEntity("domain/user?name={name}",
// String.class, params);
String body=strResults.getBody();
//返回user對象
ResponseEntity<User> userResult = restTemplate.getForEntity("domain/user?name={1}",
User.class, "qiu");
User user=userResult.getBody();
(2)post
- 和get不同的是,方法中多了一個request對象,該參數(shù)是一個普通對象,也可以是一個httpentity對象。如果是一個普通對象,resttemplate會將請求轉(zhuǎn)為httpentity對象處理,request的內(nèi)容會被視作為完成的body來處理;如果是httpentity對象,就會當(dāng)做一個完整的http請求來處理,不僅包括body還包括header等內(nèi)容。
api:
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,Class<T> responseType, Object... uriVariables)
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,Class<T> responseType, Map<String, ?> uriVariables)
public <T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType)
2、restTemplate簡單使用配置
@Configuration
public class RestConfiguration {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate(simpleClientHttpRequestFactory());
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
//設(shè)置超時時間
factory.setReadTimeout(5000);//ms
factory.setConnectTimeout(15000);//ms
return factory;
}
}
3、restTemplate一些高級應(yīng)用(替換底層連接、配置轉(zhuǎn)換器、配置攔截器等等)
http://www.itdecent.cn/p/b4e479a6f5a8
https://www.xncoding.com/2017/07/06/spring/sb-restclient.html
https://blog.csdn.net/w05980598/article/details/79166507
三、Ribbon負(fù)載均衡策略
- 在Ribbon中使用AbastractBalanceRule作為負(fù)載均衡的抽象類。在該類中,定義了ILoaderBalancer對象,該對象能夠在具體實(shí)現(xiàn)服務(wù)策略時候,獲取一些負(fù)載均衡中維護(hù)的信息作為分配依據(jù),并以此設(shè)計一些算法來實(shí)現(xiàn)針對特定場景的 高效策略。

| 策略名 | 策略聲明 | 策略描述 | 實(shí)現(xiàn)說明 |
|---|---|---|---|
| BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule | 選擇一個最小的并發(fā)請求的server | 逐個考察Server,如果Server被tripped了,則忽略,在選擇其中ActiveRequestsCount最小的server |
| ZoneAvoidanceRule | public class ZoneAvoidanceRule extends PredicateBasedRule | 復(fù)合判斷server所在區(qū)域的性能和server的可用性選擇server | 使 用ZoneAvoidancePredicate和AvailabilityPredicate來判斷是否選擇某個server,前一個判斷判定一個 zone的運(yùn)行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于過濾掉連接數(shù)過多的 Server。 |
| RandomRule | public class RandomRule extends AbstractLoadBalancerRule | 隨機(jī)選擇一個server | 該策略實(shí)現(xiàn)了從服務(wù)實(shí)例清單中隨機(jī)選擇一個服務(wù)實(shí)例的功能。 |
| RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式輪詢選擇server | 該策略實(shí)現(xiàn)了按照線性輪詢的方式依次選擇每個服務(wù)實(shí)例的功能。 |
| WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根據(jù)相應(yīng)時間分配一個weight,相應(yīng)時間越長,weight越小,被選中的可能性越低。 | 一 個后臺線程定期的從status里面讀取評價響應(yīng)時間,為每個server計算一個weight。Weight的計算也比較簡單responsetime 減去每個server自己平均的responsetime是server的權(quán)重。當(dāng)剛開始運(yùn)行,沒有形成statas時,使用roubine策略選擇 server。 |
| RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 對選定的負(fù)載均衡策略機(jī)上重試機(jī)制。 | 在一個配置時間段內(nèi)當(dāng)選擇server不成功,則一直嘗試使用subRule的方式選擇一個可用的server |
四、Ribbon配置使用
1、默認(rèn)實(shí)現(xiàn)
- 由于Ribbon中定義的每 一個接口都有多種不同的策略實(shí)現(xiàn),同時這些接口之間又有 一定的 依賴關(guān)系,這使得第 一次使用rbbion的開發(fā)者很難上手,不知道如何選擇具體的實(shí)現(xiàn)策略以及如何組織它們 的關(guān)系。 Spring Cloud ribbon中的自動化配置恰恰 能夠解決這樣的痛點(diǎn),在引入Spring Cloud Ribbon的 依賴之后, 就能夠自動化構(gòu)建下面這些接口的實(shí)現(xiàn)。
com.netflix.client.config.IClientConfig:Ribbon的客戶端配置,默認(rèn)采用com.netflix.client.config.DefaultClientConfigImpl實(shí)現(xiàn)。
com.netflix.loadbalancer.IRule:Ribbon的負(fù)載均衡策略,默認(rèn)采用com.netflix.loadbalancer.ZoneAvoidanceRule實(shí)現(xiàn),該策略能夠在多區(qū)域環(huán)境下選出最佳區(qū)域的實(shí)例進(jìn)行訪問。
com.netflix.loadbalancer.IPing:Ribbon的實(shí)例檢查策略,默認(rèn)采用com.netflix.loadbalancer.NoOpPing實(shí)現(xiàn),該檢查策略是一個特殊的實(shí)現(xiàn),實(shí)際上它并不會檢查實(shí)例是否可用,而是始終返回true,默認(rèn)認(rèn)為所有服務(wù)實(shí)例都是可用的。
com.netflix.loadbalancer.ServerList:服務(wù)實(shí)例清單的維護(hù)機(jī)制,默認(rèn)采用com.netflix.loadbalancer.ConfigurationBasedServerList實(shí)現(xiàn)。
com.netflix.loadbalancer.ServerListFilter:服務(wù)實(shí)例清單過濾機(jī)制,默認(rèn)采org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter,該策略能夠優(yōu)先過濾出與請求方處于同區(qū)域的服務(wù)實(shí)例。
com.netflix.loadbalancer.ILoadBalancer:負(fù)載均衡器,默認(rèn)采用com.netflix.loadbalancer.ZoneAwareLoadBalancer實(shí)現(xiàn),它具備了區(qū)域感知的能力。
2、自定義配置文件(全局)
@Configuration
public class ConfigBeans {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
/**自定義配置ribbon負(fù)載均衡算法
* @return
*/
@Bean
public IRule myRule(){
//return new RoundRobinRule();//輪詢
//return new RetryRule();//重試
return new BestAvailableRule();
}
}
3、針對某一個服務(wù)調(diào)用私人定制
- 如果要自定義Ribbon配置, 則需要把這個配置類放在@SpringBootApplication掃不到的包中(@ComponentScan),因?yàn)槿绻梢話叩阶远x的Ribbon配置類的話,那么會對所有的Riboon都生效,也就是說這種情況下所有的微服務(wù)的負(fù)載均衡算法都是相同的。
https://blog.csdn.net/u010816545/article/details/80461957
4、脫離eureka使用
#取消Ribbon使用Eureka
ribbon.eureka.enabled=false
#配置Ribbon能訪問 的微服務(wù)節(jié)點(diǎn),多個節(jié)點(diǎn)用逗號隔開
microservice-provider-user.ribbon.listOfServers=localhost:8001,localhost:8002

