天天看點

【夯實Spring Cloud】Spring Cloud中自定義Ribbon負載均衡政策

本文屬于【夯實Spring Cloud】系列文章,該系列旨在用通俗易懂的語言,帶大家了解和學習Spring Cloud技術,希望能給讀者帶來一些幹貨。系列目錄如下:

【夯實Spring Cloud】Dubbo沉睡5年,Spring Cloud開始崛起!

【夯實Spring Cloud】Spring Cloud中基于maven的分布式項目架構的搭建

【夯實Spring Cloud】Spring Cloud中的Eureka服務注冊與發現詳解

【夯實Spring Cloud】Spring Cloud中如何完善Eureka中的服務資訊

【夯實Spring Cloud】Spring Cloud中使用Eureka叢集搭建高可用服務注冊中心

【夯實Spring Cloud】Spring Cloud中的Eureka和Zookeeper的差別在哪?

【夯實Spring Cloud】Spring Cloud中使用Ribbon實作負載均衡詳解(上)

【夯實Spring Cloud】Spring Cloud中使用Ribbon實作負載均衡詳解(下)

【夯實Spring Cloud】Spring Cloud中自定義Ribbon負載均衡政策

【夯實Spring Cloud】Spring Cloud中使用Feign實作負載均衡詳

【夯實Srping Cloud】Spring Cloud中使用Hystrix實作斷路器原理詳解(上)

【夯實Srping Cloud】Spring Cloud中使用Hystrix實作斷路器原理詳解(下)

【夯實Spring Cloud】Spring Cloud中使用Zuul實作路由網關詳解

【夯實Spring Cloud】Spring Cloud分布式配置中心詳解

【夯實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 方法。是以,自定義政策分兩步走:

  1. 實作 AbstractLoadBalancerRule 類
  2. 重寫 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),然後仍然在浏覽器輸入:http://localhost:9001/consumer/order/get/1 來測試一下即可。

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

源碼下載下傳位址:https://gitee.com/eson15/springcloud_study

更多優質文章請關注我的微信公衆号【武哥聊程式設計】,回複“資源”、“架構”、“履歷”等關鍵詞,可以領取海量優質的視訊學習資源。大家共同進步。

【夯實Spring Cloud】Spring Cloud中自定義Ribbon負載均衡政策