<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [高可用/負載均衡] Ribbon LoadBalancer: 開源的客戶端式負載均衡框架

      0 序言

      • 某項目上,原先為自建的數據庫集群提供了負載均衡IP服務器(簡稱: ELB IP Server),客戶端的數據庫請求URL都統一走ELB IP。但隨著業務量的增長,識別到一個嚴峻的現實:
      • 其一,考慮到未來的業務增長情況,云廠商提供的 ELB IP Server 云服務的入網帶寬必將完全無法滿足本項目的訴求。
      • 其二,云廠商提供的 ELB IP Server 的費用較為昂貴,實在是不劃算。

      除了入網帶寬的使用量較高外,云廠商ELB 服務提供的其他方面的資源指標,使用量均極低(有浪費錢的嫌疑)。

      • 為此開始嘗試:取消服務端式負載均衡器,自行實現客戶端式的負載均衡器

      經過一番研究,開源的、支持Java、與spring生態框架獨立/解耦的、負載均衡器 Ribbon,成為個人的首選。

      即:筆者此時的訴求之一是,不需要引入spring框架,與其解耦。

      1 概述:Ribbon LoadBalancer: 開源負載均衡器

      負載均衡的概念

      • 負載均衡是一種通過【分發請求】來優化服務器資源利用率提高系統性能的技術。

      它在微服務架構中尤為重要,常見的負載均衡方式包括服務端負載均衡客戶端負載均衡

      image

      • 服務端負載均衡是指請求首先被發送到【負載均衡服務器】,然后由該服務器根據【負載均衡算法】(如輪詢、最小連接數等)將【請求分發】到后端服務器進行處理。
      • 常見的服務端負載均衡工具包括: 硬件設備(如F5)和軟件(如Nginx、LVS)。
      • 這種方式的優點是: 客戶端無感知、無需關心負載均衡的邏輯,所有的均衡操作都由服務端完成。

      image

      • 客戶端負載均衡則是由客戶端直接從服務注冊中心(如Nacos、Eureka)獲取服務列表,并根據負載均衡算法選擇目標服務器進行請求分發

      Spring Cloud中的Ribbon為例,客戶端通過RestTemplate觸發負載均衡。
      客戶端負載均衡的特點無需額外的負載均衡服務器(例如: ELB IP Server),分發邏輯完全由客戶端實現。

      image

      • 兩者的主要區別在于:負載均衡的實現位置。

      服務端負載均衡依賴于專門的負載均衡服務器,而客戶端負載均衡則由客戶端自行完成分發邏輯。

      客戶端式負載均衡方案的實現原理

      1. ?服務發現客戶端?,從注冊中心獲取服務實例列表并緩存。
      2. 客戶端請求被 ?負載均衡攔截器? 截獲(如 @LoadBalanced 標記的 RestTemplate/WebClient)。

      org.springframework.cloud.client.loadbalancer.LoadBalanced
      org.springframework.web.client.RestTemplate

      1. 攔截器調用 ?LoadBalancerClient

      org.springframework.cloud.client.loadbalancer.LoadBalancerClient
      org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient

      4.? LoadBalancerClient? 調用底層的負載均衡器 (Ribbon / SCL) 選擇一個實例。
      5. 負載均衡器根據 ?負載均衡策略? 從可用實例列表中選擇一個目標實例。
      6. 請求最終被?轉發到選定的實例。

      關鍵問題:負載均衡與請求客戶端、連接池的集成

      • Ribbon 等本身只是一個客戶端負載均衡器,它負責從服務列表里挑一臺機器,把原請求 URL 中的“服務名”替換成這臺服務器的真實 IP+端口。

      真正發出 HTTP 請求的是下游的 HTTP 客戶端

      • 若還想把“連接池”能力加進來,就是把這個客戶端換成支持池化的實現(OkHttp / Apache HttpClient),并讓它復用 Ribbon 等負載均衡框架已挑好的地址。

      Ribbon LoadBalancer: 開源的客戶端式負載均衡框架

      • Ribbon
      • Ribbon有很多子模塊,官方文檔中說明,目前 Netflix 公司主要用于生產環境的 Ribbon 子模塊如下:
      • ribbon-core:Ribbon 的核心API。
      • ribbon-loadbalancer:可以獨立使用或與其他模塊一起使用的負載均衡器 API。
      • ribbon-eureka:Ribbon 結合 注冊中心 Eureka 客戶端的 API,為負載均衡器提供動態服務注冊列表信息。

      image

      • Ribbon LoadBalancer
      • 起源于 ?Netflix OSS,曾是 Spring Cloud ?默認的客戶端負載均衡解決方案。
      • Ribbon 是一個獨立的、較為成熟的庫,被廣泛集成到 Spring Cloud Netflix 組件(如 Zuul、Feign)中。
      • 已進入維護模式,Netflix 官方不再積極開發新功能。
      • 技術架構與依賴?
      • ?非響應式 (阻塞式):?? 核心 API 基于線程池和阻塞調用,在響應式編程場景下兼容性較差。
      • ?依賴較重:?? 包含大量 Netflix 的內部組件 (如 Archaius 配置系統),包體積和復雜度較高。
      • ?獨立的負載均衡器:?? 需要額外的客戶端負載均衡器實現 (如 RibbonLoadBalancerClient)。

      springcloud 與 ribbon 整合

      此小節旨在解釋 spring cloud 項目中,如何與 ribbon 集成。ribbon 也可完全獨立于 spring 項目,獨立運行。

      Ribbon 與 RestTemplate 整合使用

      • Spring Cloud 構建的微服務系統中,Ribbon 作為服務消費者的負載均衡器,有2種使用方式:
      • 一種是和 RestTemplate 相結合;
      • 另一種是和 Feign 相結合。
      • 那么,Spring Cloud框架中,Ribbon (負載均衡器) 是如何與 Spring 的 RestTemplate / WebClient 集成的?

      下面用一張圖來看看 RestTemplate 基于 Ribbon 的遠程調用:

      image

      from : http://www.rzrgm.cn/chiangchou/p/ribbon-1.html

      • RestTemplate 本身是不具備【負載均衡】的能力的。
      1 RestTemplate 是 Spring Resources 中一個訪問第三方 RESTful API 接口的網絡請求框架,用于執行HTTP請求。
      2 其暴露了一系列的模板方法API,便于操作底層的HTTP客戶端庫,如JDK的HttpURLConnection、Apache HttpComponents等。
      3 RestTemplate 是用來消費 REST 服務的,所以 RestTemplate 的主要方法都與 REST 的 Http協議的一些方法緊密相連,例如 HEAD、GET、POST、PUT、DELETE 和 OPTIONS 等方法。
      這些方法在 RestTemplate 類對應的方法為 headForHeaders()、getForObject()、postForObject()、put() 和 delete() 等。
      
      4 RestTemplate通常作為【共享組件】使用,其配置不支持【并發修改】,因此通常在【啟動時】準備好配置。
        如果需要,可以在啟動時創建多個配置不同的RestTemplate實例。
        這些實例可以使用相同的底層`ClientHttpRequestFactory`,如果它們需要共享HTTP客戶端資源。
      
      • 如果 RestTemplate 未使用 @LoadBalanced 標記,就通過服務名的形式來調用,必然會報錯。
      • @LoadBalanced 標記后,調用 RestTemplateREST 方法就會通過【負載均衡】的方式通過一定的負載策略【路由】到某個【服務實例】上。

      此時,其底層負責負載均衡的組件就是 Ribbon

      springcloud 、注冊中心 eureka 、負載均衡器 ribbon 三者的整合

      • 與 eureka 整合到 springcloud 類似,springcloud 提供了對應的 spring-cloud-starter-netflix-eureka-client(server) 依賴包
      • ribbon 則整合到了 spring-cloud-starter-netflix-ribbon 中。

      一般也不需要單獨引入 ribbon 的依賴包,spring-cloud-starter-netflix-eureka-client 中已經依賴了 spring-cloud-starter-netflix-ribbon
      因此,我們引入了 spring-cloud-starter-netflix-eureka-client 就可以使用 Ribbon 的功能了。

      image

      springcloud 、注冊中心 nacos 、負載均衡器 ribbon 三者的整合

      略,類同 eureka 。

      客戶端式負載均衡框架的同類競品項目

      • ?Spring Cloud LoadBalancer (SCL)
      • Spring 官方在 ?Spring Cloud Hoxton (2020年)?? 推出,旨在替代 Ribbon。
      • 是 ?Spring Cloud Commons? 項目的一部分,與 Spring 生態集成度更高。
      • 目前作為 ?Spring Cloud 官方推薦的負載均衡解決方案,持續更新迭代。

      spring項目中,若同時引了 spring-cloud-starter-netflix-ribbonspring-cloud-loadbalancer 會沖突,用 spring.cloud.loadbalancer.ribbon.enabled=false 可回退到 Ribbon

      • 技術架構與依賴?
      • ?響應式優先:?? 核心接口 ReactiveLoadBalancer 基于 ?Project Reactor?(Reactor Core),天然支持響應式編程,同時對阻塞式調用提供適配。
      • ?輕量級:?? 源碼簡潔,依賴少 (spring-cloud-starter-loadbalancer),啟動更快。
      • ?Spring原生集成:?? 與 Spring 框架深度集成(如 Environment、BeanFactory),配置管理更簡單。(既是優點,也是缺點)

      Maven依賴

      <!-- 客戶端式負載均衡器 https://github.com/Netflix/ribbon | https://mvnrepository.com/artifact/com.netflix.ribbon/ribbon -->
      <dependency>
        <groupId>com.netflix.ribbon</groupId>
        <artifactId>ribbon</artifactId>
        <!-- 2.7.18 -->
        <version>${ribbon.version}</version>
      </dependency>
      <dependency>
        <groupId>com.netflix.ribbon</groupId>
        <artifactId>ribbon-core</artifactId>
        <version>${ribbon.version}</version>
      </dependency>
      <dependency>
        <groupId>com.netflix.ribbon</groupId>
        <artifactId>ribbon-loadbalancer</artifactId>
        <version>${ribbon.version}</version>
      </dependency>
      

      2 Ribbon LoadBalancer 核心 API

      • IClientConfig:Ribbon 客戶端配置類,默認實現是 DefaultClientConfigImpl。
      • IRule:負載均衡策略規則組件,默認實現是 ZoneAvoidanceRule。
      • IPing:判斷 Server 是否存活,默認實現是 DummyPing,永遠都是返回 true。
      • ServerList:獲取 Server 的組件,默認實現類為 ConfigurationBasedServerList,從配置文件獲取。
      • ServerListUpdater:Server 列表更新組件,默認實現類為 PollingServerListUpdater。
      • ServerListFilter:過濾可用的 Server 列表,默認實現類為 ZonePreferenceServerListFilter。
      • RibbonLoadBalancerContext:負載均衡客戶端。
      • RetryHandler:重試處理器,默認實現類為 DefaultLoadBalancerRetryHandler。

      IClientConfig : 客戶端配置

      • com.netflix.client.config.IClientConfig : 管理客戶端配置的核心接口,它的默認實現類是 DefaultClientConfigImpl

      可以看到在創建 IClientConfig 時,設置了 Ribbon 客戶端默認的連接和讀取超時時間為 1 秒,例如讀取如果超過1秒,就會返回超時,這兩個一般需要根據實際情況來調整。

      import com.netflix.client.config.IClientConfig;
      import com.netflix.client.config.CommonClientConfigKey;
      
      @Bean
      @ConditionalOnMissingBean
      public IClientConfig ribbonClientConfig() {
          DefaultClientConfigImpl config = new DefaultClientConfigImpl();
          // 加載配置
          config.loadProperties(this.name);
          // 連接超時默認 1 秒
          config.set(CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT);
          // 讀取超時默認 1 秒
          config.set(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT);
          config.set(CommonClientConfigKey.GZipPayload, DEFAULT_GZIP_PAYLOAD);
          return config;
      }
      
      • com.netflix.client.config.CommonClientConfigKey

      這個類定義了 Ribbon 客戶端相關的所有配置的鍵常量,可以通過這個類來看有哪些配置。

      https://github.com/Netflix/ribbon/blob/v2.7.18/ribbon-core/src/main/java/com/netflix/client/config/CommonClientConfigKey.java

      • 進入到 DefaultClientConfigImpl,可以看到 CommonClientConfigKey 中的每個配置都對應了一個默認值。

      在加載配置的時候,如果用戶沒有定制配置,就會使用默認的配置。

      https://github.com/Netflix/ribbon/blob/v2.7.18/ribbon-archaius/src/main/java/com/netflix/client/config/DefaultClientConfigImpl.java
      https://github.com/Netflix/ribbon/blob/v2.7.18/ribbon-core/src/test/java/com/netflix/client/config/DefaultClientConfigImplTest.java

      也可以在配置文件中定制配置,例如配置超時和重試:

      # 全局配置
      ribbon:
        # 客戶端讀取超時時間
        ReadTimeout: 3000
        # 客戶端連接超時時間
        ConnectTimeout: 3000
        # 默認只重試 GET,設置為 true 時將重試所有類型,如 POST、PUT、DELETE
        OkToRetryOnAllOperations: false
        # 重試次數
        MaxAutoRetries: 1
        # 最多重試幾個實例
        MaxAutoRetriesNextServer: 1
      
      # 只針對 demo-producer 客戶端
      demo-producer:
        ribbon:
          # 客戶端讀取超時時間
          ReadTimeout: 5000
          # 客戶端連接超時時間
          ConnectTimeout: 3000
      

      IRule : 均衡策略

      • IRule 是最終選擇 Server 的策略規則類,核心的接口就是 choose
      public interface IRule{
          // 選擇 Server
          public Server choose(Object key);
      
          // 設置 ILoadBalancer
          public void setLoadBalancer(ILoadBalancer lb);
      
          // 獲取 ILoadBalancer
          public ILoadBalancer getLoadBalancer();
      }
      
      • Ribbon 提供了豐富的負載均衡策略,我們也可以通過配置指定使用某個均衡策略。下面是整個Ribbon提供的 IRule 均衡策略。

      image

      策略類 命名 描述
      RandomRule 隨機策略 隨機選擇 server
      RoundRobinRule 輪詢策略 按順序循環選擇 server
      RetryRule 重試策略 在一個配置時間段內當選擇 server 不成功,則一直嘗試選擇一個可用的 server
      BestAvailableRule 最低并發策略 逐個考察 server,如果 server 斷路器打開,則忽略,再選擇其中并發連接最低的 server
      AvailabilityFilteringRule 可用過濾策略 過濾掉一直連接失敗并被標記為 circuit tripped 的 server,過濾掉那些高并發連接的 server(active connections 超過配置的閾值)
      ResponseTimeWeightedRule 響應時間加權策略 根據 server 的響應時間分配權重。響應時間越長,權重越低,被選擇到的概率就越低;響應時間越短,權重越高,被選擇到的概率就越高。這個策略很貼切,綜合了各種因素,如:網絡、磁盤、IO 等,這些因素直接影響著響應時間
      ZoneAvoidanceRule 區域權衡策略 綜合判斷 server 所在區域的性能和 server 的可用性輪詢選擇 server,并且判定一個 AWS Zone 的運行性能是否可用,剔除不可用的 Zone 中的所有 server

      例如: RandomRule => com.netflix.loadbalancer.RandomRule

      • RoundRobinRule:輪詢
      • RandomRule:隨機
      • RetryRule:先按照輪詢策略獲取服務,如果獲取服務失敗則在指定時間內進行重試,獲取可用的服務
      • WeightedResponseTimeRule:對輪詢的擴展,響應速度越快的實例選擇權重越大,越容易被選擇
      • BestAvailableRule:會先過濾掉由于多次訪問故障而處于斷路器跳閘狀態的服務,然后選擇一個并發量最小的服務
      • AvailabiliyFilteringRule:先過濾掉故障實例,再選擇并發較小的實例
      • ZoneAvoidanceRule:默認規則,復合判斷server所在區域的性能和server的可用性選擇服務器

      IPing : 服務檢查

      • com.netflix.loadbalancer.IPing :

      用于定期檢查 Server 的可用性的,它只提供了一個接口,用來判斷 Server 是否存活:

      package com.netflix.loadbalancer;
      
      public interface IPing {
          boolean isAlive(Server var1);
      }
      
      • IPing 也提供了多種策略可選。
        image

      image

      下面是整個 IPing 體系結構:

      image

      ServerList : 獲取服務列表

      • ServerList 提供了2個接口: 一個是第一次獲取 Server 列表,一個是更新 Server 列表

      其中 getUpdatedListOfServers 會每被 Loadbalancer 隔 30 秒調一次來更新 allServerList。

      public interface ServerList<T extends Server> {
      
          public List<T> getInitialListOfServers();
      
          /**
           * Return updated list of servers. This is called say every 30 secs
           * (configurable) by the Loadbalancer's Ping cycle
           */
          public List<T> getUpdatedListOfServers();
      }
      
      • ServerList 也提供了多種實現

      ServerList 體系結構如下:

      image

      image

      ServerListFilter : 過濾服務

      • ServerListFilter 提供了一個接口用來過濾出可用的 Server。
      public interface ServerListFilter<T extends Server> {
          public List<T> getFilteredListOfServers(List<T> servers);
      }
      

      image

      ServerListUpdater :服務列表更新

      • ServerListUpdater 有多個接口,最核心的就是 start 開啟定時任務調用 updateAction 來更新 allServerList
      public interface ServerListUpdater {
      
          /**
           * an interface for the updateAction that actually executes a server list update
           */
          public interface UpdateAction {
              void doUpdate();
          }
      
          /**
           * start the serverList updater with the given update action
           * This call should be idempotent.
           */
          void start(UpdateAction updateAction);
      }
      
      • 默認有兩個實現類:

      image

      ILoadBalancer : 負載均衡器

      • ILoadBalancer 是負載均衡選擇服務的核心接口,主要提供了如下的獲取Server列表和根據客戶端名稱選擇Server的接口。
      public interface ILoadBalancer {
          // 添加Server
          public void addServers(List<Server> newServers);
      
          // 根據key選擇一個Server
          public Server chooseServer(Object key);
      
          // 獲取存活的Server列表,返回 upServerList
          public List<Server> getReachableServers();
      
          // 獲取所有Server列表,返回 allServerList
          public List<Server> getAllServers();
      }
      

      image

      Z 案例實踐

      CASE 實現客戶端式負載均衡器(快速入門版)

      package com.knowdata.framework.study.ribbon.lb;
      
      import java.io.IOException;
      import java.net.HttpURLConnection;
      import java.net.URL;
      import java.util.Arrays;
      import java.util.List;
      
      import com.netflix.loadbalancer.BaseLoadBalancer;
      import com.netflix.loadbalancer.RoundRobinRule;
      import com.netflix.loadbalancer.Server;
      
      /*
       * @description Ribbon 負載均衡框架的快速入門示例
       * @updateTime 2025/09/14 16:39
       */
      public class RibbonQuickStartTest {
          public static void main(String[] args) throws Exception {
              // 定義目標服務器列表
              List<Server> serverList = Arrays.asList(
                  new Server("localhost", 8086),
                  new Server("localhost", 8086),
                  new Server("localhost", 8086)
              );
      
              // 創建(客戶端式)負載均衡器
              BaseLoadBalancer loadBalancer = new BaseLoadBalancer();
              loadBalancer.setServersList(serverList);
      
              // 配置負載均衡策略(可選,默認為輪詢)
              loadBalancer.setRule(new RoundRobinRule());
              // 其他策略示例:
              // loadBalancer.setRule(new RandomRule());
              // loadBalancer.setRule(new WeightedResponseTimeRule());
      
              // 模擬多次請求,查看負載均衡效果
              for (int i = 0; i < 10; i++) {
                  Server server = loadBalancer.chooseServer(null);
                  System.out.println("第 " + (i + 1) + " 次請求,選中服務器: " + server.getHostPort());
                  sendRequest(server);
              }
          }
      
          private static void sendRequest(Server server) {
              try {
                  URL url = new URL("http://" + server.getHost() + ":" + server.getPort() + "/api/hello");
                  HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                  connection.setRequestMethod("GET");
                  int responseCode = connection.getResponseCode();
                  System.out.println("響應碼: " + responseCode);
                  connection.disconnect();
              } catch (IOException e) {
                  System.err.println("請求失敗: " + e.getMessage());
              }
          }
      }
      

      Y 推薦文獻

      • Ribbon

      X 參考文獻

      posted @ 2025-09-14 23:41  千千寰宇  閱讀(1663)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲国产v高清在线观看| 国产免费午夜福利蜜芽无码| 18禁无遮挡啪啪无码网站| 国产a在亚洲线播放| 深田えいみ禁欲后被隔壁人妻| 欧美人与动交视频在线观看| 欧美激情一区二区三区成人 | 精品国产AV无码一区二区三区 | 国色天香成人一区二区| 国产婷婷综合在线视频中文| 国产超碰无码最新上传| 九九热精品视频免费在线| 国产精品v欧美精品∨日韩| 亚洲国产色婷婷久久99精品91| 国产一区二区一卡二卡| 精品一区二区久久久久久久网站| 国产粉嫩美女一区二区三| 好吊视频专区一区二区三区| 97人妻人人揉人人躁人人| 色悠悠国产精品免费在线| 亚洲av成人无码天堂| 性欧美vr高清极品| 国产边打电话边被躁视频| 精品国产乱码久久久久夜深人妻| 污网站在线观看视频| 成人精品一区二区三区在线观看| 精品无人区一码二码三码| 日韩人妻一区中文字幕| AV最新高清无码专区| 国产精品蜜臀av在线一区| 婷婷六月色| 亚洲偷偷自拍码高清视频| 中文字幕国产在线精品| 亚洲国产成人资源在线| 亚洲一区二区三区小蜜桃| 亚洲国产高清av网站| 精品无码久久久久国产电影| 成年女人免费碰碰视频| 九九热精品在线视频免费| 精品人妻一区二区三区蜜臀| 国产乱人伦偷精品视频下|