Spring Cloud:自定義 Ribbon 負載均衡策略

程式設計師私房菜發表於2019-01-22

Spring Cloud:自定義 Ribbon 負載均衡策略

閱讀文字大概需要 3 分鐘。

在前兩篇文章中,我對 Ribbon 的使用做了詳細的介紹:

Spring Cloud:使用Ribbon實現負載均衡詳解(上)

Spring Cloud:使用Ribbon實現負載均衡詳解(下)

但是使用的是 Ribbon 自帶的負載均衡策略,那麼 Ribbon 是否可以根據實際情況,自定義負載均衡策略呢?答案是肯定的,這一篇文章主要來介紹一下 Ribbon 如何自定義負載均衡策略。

1. 主啟動類處理

還是使用上一節的客戶端程式碼,先回憶一下相關內容:三個訂單服務提供者,服務名稱叫:MICROSERVICE-ORDER,埠分別為 8001、8002 和 8003。Eureka 叢集三個服務,埠分別為 7001、7002 和 7003。

上一節主要是使用 Ribbon 的輪詢和隨機策略,來測試負載均衡。這一節我們自定義一個策略。首先要在啟動類中新增 @RibbonClient 註解,如下:

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "MICROSERVICE-ORDER", configuration = MyRuleConfig.class)
public class OrderConsumer {

   public static void main(String[] args) {
       SpringApplication.run(OrderConsumer.class, args);
   }
}

name 用來指定需要均衡的服務,即三個訂單服務,configuration 用來指定所用的策略配置,這裡使用我們自定義的一個配置 MyRuleConfig。接下來,我們來定義這個配置。

2. 自定義配置

這個配置的位置有個地方需要注意:就是所在的包不能和主啟動類在同一個包下面,這是官方文件提到的注意事項。所以我們自己新建一個和主啟動類所在的包同級的包,然後寫 MyRuleConfig。

/**
* 自定義規則
* @author shengwu ni
*/

@Configuration
public class MyRuleConfig {
   @Bean
   public IRule myselfRule() {
       // 指定策略:我們自定義的策略
       return new CustomRule();
   }
}

3. 自定義策略

OK,接下來就是實現這個自定義策略:CustomRule了。我們假設自己定義的策略如下:

還是按照輪詢的方式來選擇服務,但是每個被輪詢到的服務,接下來訪問4次(預設是1次),4次訪問完之後,再切換到下一個服務,訪問4次,以此類推。

拿到這個需求之後,我們需要改寫策略了,根據官方 github 原始碼可以知道,類似於輪詢、隨機這種策略,都是繼承了 AbstractLoadBalancerRule 類,然後重寫 choose 方法。所以,自定義策略分兩步走:

  • 實現 AbstractLoadBalancerRule 類

  • 重寫 choose 方法

我先把程式碼複製一下,然後來分析一下:

/**
* 自定義規則
* @author shengwu ni
*/

public class CustomRule extends AbstractLoadBalancerRule {

   /**
    * 總共被呼叫的次數,目前要求每臺被呼叫4次
     */

   private int total = 0;
   /**
    * 當前提供服務列表的索引
    */

   private int currentIndex = 0;

   @Override public void initWithNiwsConfig(IClientConfig iClientConfig) {
   }

   /**
    * 在choose方法中,自定義我們自己的規則,返回的Server就是具體選擇出來的服務
    * 自己的規則:按照輪詢的規則,但是每個被輪詢到的服務呼叫5次。
    * @param o
    * @return
    */

   @Override public Server choose(Object o) {
       // 獲取負載均衡器lb
       ILoadBalancer lb = getLoadBalancer();
       if (lb == null) {
           return null;
       }

       Server server = null;
       while (server == null) {
           if (Thread.interrupted()) {
               return null;
           }
           // 獲取可用服務列表
           List<Server> upList = lb.getReachableServers();
           // 獲取所有服務列表
           List<Server> allList = lb.getAllServers();
           int serverCount = allList.size();
           if (serverCount == 0) {
               return null;
           }

           // 若呼叫次數小於4次,一直呼叫可用服務列表中索引為 currentIndex 的服務
           if(total < 4)
           {
               server = upList.get(currentIndex);
               total++;
           } else {
               // 到了4次之後,服務列表中的索引值++,表示下一個呼叫下一個服務
               total = 0;
               currentIndex++;
               // 當索引大於可用服務列表的size時,要重新從頭開始
               currentIndex = currentIndex % upList.size();

               if (server == null) {
                   Thread.yield();
                   continue;
               }

               if (server.isAlive()) {
                   return (server);
               }

               server = null;
               Thread.yield();
           }
       }
       return server;
   }
}

我來簡單分析一下程式碼:首先獲取 ILoadBalancer 物件,該物件可以獲取當前的服務。我們需要獲取當前可用的服務列表和當前所有的服務列表。

total 表示服務被呼叫的次數,到4次,該服務呼叫停止,切換到下一個可用服務;currentIndex 表示當前可用服務列表中的索引。若呼叫次數小於4次,一直呼叫可用服務列表中索引為 currentIndex 的服務,到了4次之後,服務列表中的索引值++,表示下一個呼叫下一個服務。具體可以看程式碼中的註釋。

4. 測試一下

OK,到這裡,自定義的負載均衡策略就完成了,我們啟動三個 eureka 叢集和三個訂單服務提供者,然後啟動消費方客戶端(埠9001),然後仍然在瀏覽器輸入:

來測試一下即可。

正常情況:當前訂單提供服務會被呼叫四次,然後切換到另一個訂單服務,輪流切換。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31558358/viewspace-2564425/,如需轉載,請註明出處,否則將追究法律責任。

相關文章