負載均衡-Ribbon

一. Ribbon概述

Spring Cloud Ribbon是基于Netflix Ribbon 實現(xiàn)的一套客戶端的負載均衡工具,Ribbon客戶端組件提 供一系列的完善的配置,如超時,重試等。通過Load Balancer獲取到服務(wù)提供的所有機器實例, Ribbon會自動基于某種規(guī)則(輪詢,隨機)去調(diào)用這些服務(wù)。Ribbon也可以實現(xiàn)我們自己的負載均衡算法。

二. 主流負載均衡

  • 集中式負載均衡

在消費者和服務(wù)提供方中間使用獨立的代理方式進行負載,有硬件的(比如 F5),也有軟件的(比如 Nginx)。

  • 客戶端負載均衡

客戶端會有一個服務(wù)器地址列表,在發(fā)送請求前通過負載均衡算法選擇 一個服務(wù)器,然后進行訪問,這是客戶端負載均衡。

三. 常見負載均衡算法

算法就是從服務(wù)列表中按某個規(guī)則選取一個。

  • 隨機,通過隨機選擇服務(wù)進行執(zhí)行,一般這種方式使用較少;

  • 輪訓,負載均衡默認實現(xiàn)方式,請求來之后排隊處理;

  • 加權(quán)輪訓,通過對服務(wù)器性能的分型,給高配置,低負載的服務(wù)器分配更高的權(quán)重,均衡各個 服務(wù)器的壓力;

  • 地址Hash,通過客戶端請求的地址的HASH值取模映射進行服務(wù)器調(diào)度。

  • 最小鏈接數(shù),即使請求均衡了,壓力不一定會均衡,最小連接數(shù)法就是根據(jù)服務(wù)器的情況,比如請求積壓數(shù)等參數(shù),將請求分配到當前壓力最小的服務(wù)器上。

服務(wù)每處理一個請求,請求數(shù)+1,處理完-1. 新的請求來時選擇請求數(shù)最少的處理。這樣性能最好的服務(wù)器接收最多的請求。

四. Ribbon 模塊

  • ribbon- loadbalancer

負載均衡模塊,可獨立使用,也可以和別的模塊一起使用。 Ribbon 內(nèi)置的負載均衡算法都實現(xiàn)在其中。

  • ribbon-eureka

基于 Eureka 封裝的模塊,能夠快速、方便地集成 Eureka。

  • ribbon-transport

基于 Netty 實現(xiàn)多協(xié)議的支持,比如 HTTP、Tcp、Udp 等。

  • ribbon-httpclient

基于 Apache HttpClient 封裝的 REST 客戶端,集成了負載均衡模塊,可以直接在項目中使用來調(diào)用接口。

  • ribbon-example

Ribbon 使用代碼示例,通過這些示例能夠讓你的學習事半功倍。

  • ribbon-core

一些比較核心且具有通用性的代碼,客戶端 API 的一些配置和其他 API 的定義。

五. Ribbon 使用

5.1 直接使用

 // 服務(wù)列表
        List<Server> serverList = Lists.newArrayList(
                new Server("localhost", 8020),
                new Server("localhost", 8021));
        // 構(gòu)建負載實例
        ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder()
                .buildFixedServerListLoadBalancer(serverList);
        // 調(diào)用 5 次來測試效果
        for (int i = 0; i < 5; i++) {
            String result = LoadBalancerCommand.<String>builder()
                    .withLoadBalancer(loadBalancer).build()
                    .submit(new ServerOperation<String>() {
                        @Override
                        public Observable<String> call(Server server) {
                            String addr = "http://" + server.getHost() + ":" +
                                    server.getPort() + "/order/findOrderByUserId/1";
                                System.out.println(" 調(diào)用地址:" + addr);
                            URL url = null;
                            try {
                                url = new URL(addr);
                                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                                conn.setRequestMethod("GET");
                                conn.connect();
                                InputStream in = conn.getInputStream();
                                byte[] data = new byte[in.available()];
                                in.read(data);
                                return Observable.just(new String(data));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            return null;
                        }
                    }).toBlocking().first();

            System.out.println(" 調(diào)用結(jié)果:" + result);
        }
    }

5.2 Spring Cloud快速整合Ribbon

<!‐‐添加ribbon的依賴‐‐> 
 <dependency> 
        <groupId>org.springframework.cloud</groupId> 
        <artifactId>spring‐cloud‐starter‐netflix‐ribbon</artifactId> 
 </dependency>

@Configuration 
public class RestConfig { 
     @Bean 
     @LoadBalanced
     public RestTemplate restTemplate() { 
           return new RestTemplate(); 
     } 
}
@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; 
}

六. Ribbon原理

Ribbon 本質(zhì)上是基于RestTemplate 的擴展點,攔截原本請求后,利用負載均衡算法在服務(wù)列表中選出一個服務(wù),替換服務(wù)名實現(xiàn)負載均衡調(diào)用的。

Ribbon實現(xiàn)原理

@LoadBalanced 原理

1.LoadBalancerAutoConfiguration 自動注入

2.@LoadBalanced利用@Qualifier作為restTemplates注入的篩選條件,篩選出具有負載均衡標識的 RestTemplate。

  1. 被@LoadBalanced注解的restTemplate會被定制,添加LoadBalancerInterceptor攔截器。


    image.png

七. Ribbon 相關(guān)接口

源碼入口RibbonClientConfiguration

  • IRule:Ribbon的負載均衡策略,默認采用ZoneAvoidanceRule實現(xiàn),該策略能夠在多區(qū)域環(huán)境下選出 最佳區(qū)域的實例進行訪問。
  • IPing:Ribbon的實例檢查策略,默認采用DummyPing實現(xiàn),該檢查策略是一個特殊的實現(xiàn),實際上 它并不會檢查實例是否可用,而是始終返回true,默認認為所有服務(wù)實例都是可用的。
  • ServerList:服務(wù)實例清單的維護機制,默認采用ConfigurationBasedServerList實現(xiàn)。
  • ServerListFilter:服務(wù)實例清單過濾機制,默認采ZonePreferenceServerListFilter,該策略能夠優(yōu)先 過濾出與請求方處于同區(qū)域的服務(wù)實例。
  • ILoadBalancer:負載均衡器,默認采用ZoneAwareLoadBalancer實現(xiàn),它具備了區(qū)域感知的能力。

八. Ribbon負載均衡策略

即IRule的實現(xiàn)


IRule實現(xiàn)
  1. RandomRule: 隨機選擇一個Server。
  2. RetryRule: 對選定的負載均衡策略機上重試機制,在一個配置時間段內(nèi)當選擇Server不成功,則一直嘗試使用subRule的方式選擇一個可用的server。
  3. RoundRobinRule: 輪詢選擇, 輪詢index,選擇index對應(yīng)位置的Server。
  4. AvailabilityFilteringRule: 過濾掉一直連接失敗的被標記為circuit tripped的后端Server,并 過濾掉那些高并發(fā)的后端Server或者使用一個AvailabilityPredicate來包含過濾server的邏輯,其 實就是檢查status里記錄的各個Server的運行狀態(tài)。
  5. BestAvailableRule: 選擇一個最小的并發(fā)請求的Server,逐個考察Server,如果Server被 tripped了,則跳過。
  6. WeightedResponseTimeRule: 根據(jù)響應(yīng)時間加權(quán),響應(yīng)時間越長,權(quán)重越小,被選中的可 能性越低。
  7. ZoneAvoidanceRule: 默認的負載均衡策略,即復(fù)合判斷Server所在區(qū)域的性能和 Server的可用性選擇Server,在沒有區(qū)域的環(huán)境下,類似于輪詢(RandomRule)
  8. NacosRule: 同集群優(yōu)先調(diào)用

九.自定義負載均衡策略

自定義

public class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {
      @Override 
      public Server choose(Object key) {
            .... .... ....
            return Server
      }
}

全局生效

@Configuration 
public class RibbonConfig { 
       /** 
         * 全局配置 
         * 指定負載均衡策略 
         * @return 
         */ 
  @Bean 
  public IRule() { 
       // 
       return new  NacosRandomWithWeightRule(); 
  } 
}

局部生效

//修改application.yml
# 被調(diào)用的微服務(wù)名 
   mall‐order: 
           ribbon: 
                 # 指定使用負載均衡策略 
                     NFLoadBalancerRuleClassName: xxxx.NacosRandomWithWeightRule

十. 饑餓加載

開啟饑餓加載,解決第一次調(diào)用慢的問題

 ribbon:
         eager‐load: 
                 # 開啟ribbon饑餓加載 
                 enabled: true 
                 # 配置mall‐user使用ribbon饑餓加載,多個使用逗號分隔 
                 clients: mall‐order
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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