自定義Ribbon負載均衡算法


Ribbon核心組件IRule

IRule:根據特定算法中從服務列表中選取一個要訪問的服務

IRule中的均衡算法:

RoundRobinRule 				 輪詢

RandomRule					 隨機

AvailabilityFilteringRule	  會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,
							還有並發的連接數量超過閾值的服務,然后對剩余的服務列表按照輪詢策略進行訪問
							
WeightedResponseTimeRule	  根據平均響應時間計算所有服務的權重,響應時間越快服務權重越大被選中的概率越高。
							剛啟動時如果統計信息不足,則使用RoundRobinRule策略,等統計信息足夠,
							會切換到WeightedResponseTimeRule
							
RetryRule					先按照RoundRobinRule的策略獲取服務,如果獲取服務失敗則在指定時間內會進行重						   試,獲取可用的服務

BestAvailableRule			 會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然后選擇一個並發量最小的							服務

ZoneAvoidanceRule			 默認規則,復合判斷server所在區域的性能和server的可用性選擇服務器

IRule中負載均衡的使用規則是:如果沒有在配置類顯示聲明,就默認使用 RoundRobinRule 輪詢負載均衡算法

如何顯示聲明算法:

在configBean 中 做如下配置:

    @Bean
    public IRule myRule() {

        return new RetryRule();//用我們重新選擇的隨機算法替代默認的輪詢。
    }

自定義配置:

在啟動該微服務的時候就能去加載我們的自定義Ribbon配置類,從而使配置生效,形如:

@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)

在啟動類之上新建一個包myrule ,然后新建一個MySelfRule類

package cn.blogsx.myrule;

/**
 * @author Alex
 * @create 2020-02-23 15:53
 **/
public class MySelfRule {
    @Bean
    public IRule myRule() {
        return  new RandomRule();
    }
}

此時仍然為 系統已有隨機算法,不過已經可以在此基礎上修改了。

在MySelfRule類同一包下,新建一個CustomRandomRule 自定義隨機規則類,並實現想要的算法:

依舊輪詢策略,但是加上新需求,每個服務器要求被調用5次。也即
以前是每台機器一次,現在是每台機器5次

package cn.blogsx.myrule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author Alex
 * @create 2020-02-23 19:37
 **/
@Configuration
public class CustomRandomRule extends AbstractLoadBalancerRule {

    private int total = 0;        //總共被調用的次數,目前要求每台被調用5次
    private int currentIndex = 0; //當前提供服務的機器號

    public Server choose(ILoadBalancer lb, Object key) {
        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;
            }

            if (total < 5) {
                server = upList.get(currentIndex);
                total++;
            } else {
                total = 0;
                currentIndex++;
                if (currentIndex >= upList.size()) {
                    currentIndex = 0;
                }
            }

            if (server == null) {
                /*
                 * The only time this should happen is if the server list were
                 * somehow trimmed. This is a transient condition. Retry after
                 * yielding.
                 */
                Thread.yield();
                continue;
            }

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

            // Shouldn't actually happen.. but must be transient or a bug.
            server = null;
            Thread.yield();
        }

        return server;

    }

    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }
}

如此進行測試即可看到每台實例被連續訪問5次,且5次后自動輪詢修改服務實例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM