五、微服務(wù)框架spring cloud組件之負(fù)載均衡器ribbon

  • 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)針對特定場景的 高效策略。
Ribbon負(fù)載均衡策略類結(jié)構(gòu)圖
策略名 策略聲明 策略描述 實(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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容