Ribbon之IRule

IRule是選擇服務(wù)的一種策略。

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)武威免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了千余家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

  • IRule

public interface IRule{
    /*
     * choose one alive server from lb.allServers or
     * lb.upServers according to key
     * 
     * @return choosen Server object. NULL is returned if none
     *  server is available 
     */
    public Server choose(Object key);
    
    public void setLoadBalancer(ILoadBalancer lb);
    
    public ILoadBalancer getLoadBalancer();    
}

choose選擇可用的服務(wù)。

  • RandomRule

隨機(jī)選擇一個UP的服務(wù)。

Random rand; // 隨機(jī)計(jì)數(shù)器

public RandomRule() {
    rand = new Random();
}

public Server choose(ILoadBalancer lb, Object key) {
    ...
    
    List<Server> upList = lb.getReachableServers();
    List<Server> allList = lb.getAllServers();
    
    int index = rand.nextInt(serverCount); // 隨機(jī)選擇一個
    server = upList.get(index);
    
    ...

}
  • RoundRobinRule

輪詢獲取服務(wù)。

public RoundRobinRule() {
    nextServerCyclicCounter = new AtomicInteger(0);// int線程安全計(jì)數(shù)器
}

public Server choose(ILoadBalancer lb, Object key) {
   
   ...
     
   int nextServerIndex = incrementAndGetModulo(serverCount); // nextServerCyclicCounter依次向后獲取服務(wù)。 
   server = allServers.get(nextServerIndex);
   
   ...

}

// 輪詢方法
private int incrementAndGetModulo(int modulo) {
    for (;;) {
        int current = nextServerCyclicCounter.get();
        int next = (current + 1) % modulo;
        if (nextServerCyclicCounter.compareAndSet(current, next))
            return next;
    }
}
  • BestAvailableRule

跳過熔斷的服務(wù),獲取請求數(shù)最少的服務(wù).通常與ServerListSubsetFilter一起使用.

public Server choose(Object key) {
    if (loadBalancerStats == null) {
        return super.choose(key); // 如果沒有l(wèi)oadBalancerStats,則采用RoundRibonRule.
    }
    List<Server> serverList = getLoadBalancer().getAllServers();
    int minimalConcurrentConnections = Integer.MAX_VALUE;
    long currentTime = System.currentTimeMillis();
    Server chosen = null;
    for (Server server: serverList) {
        ServerStats serverStats = loadBalancerStats.getSingleServerStat(server);
        if (!serverStats.isCircuitBreakerTripped(currentTime)) {
            int concurrentConnections = serverStats.getActiveRequestsCount(currentTime);
            if (concurrentConnections < minimalConcurrentConnections) {
                minimalConcurrentConnections = concurrentConnections;
                chosen = server;
            }
        }
    }
    if (chosen == null) {
        return super.choose(key);
    } else {
        return chosen;
    }
}
  • WeightedResponseTimeRule

權(quán)重的方式挑選服務(wù).服務(wù)實(shí)例響應(yīng)時間越小的服務(wù),則更容易被選中.如果服務(wù)實(shí)例響應(yīng)的時間相差不大的,排在前面的服務(wù)實(shí)例更容易被選中.

// 繼承了RoundRobinRule,也就是當(dāng)WeightedResponseTimeRule不滿足條件的時候,則采用RoundRobinRule的方式.
public class WeightedResponseTimeRule extends RoundRobinRule {

// 這個方式很重要,就是定時的計(jì)算每個服務(wù)實(shí)例的響應(yīng)時間,并以此作為每個服務(wù)實(shí)例的權(quán)重.
void initialize(ILoadBalancer lb) {        
    if (serverWeightTimer != null) {
        serverWeightTimer.cancel();
    }
    serverWeightTimer = new Timer("NFLoadBalancer-serverWeightTimer-" + name, true);
    serverWeightTimer.schedule(new DynamicServerWeightTask(), 0,serverWeightTaskTimerInterval);
    // do a initial run
    ServerWeight sw = new ServerWeight();
    sw.maintainWeights();

    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
        public void run() {
            logger.info("Stopping NFLoadBalancer-serverWeightTimer-"+ name);
            serverWeightTimer.cancel();
        }
    }));
}

// 定時任務(wù)內(nèi)部類
class DynamicServerWeightTask extends TimerTask {
    public void run() {
        ServerWeight serverWeight = new ServerWeight();
        try {
            serverWeight.maintainWeights();
        } catch (Exception e) {
            logger.error("Error running DynamicServerWeightTask for {}", name, e);
        }
    }
}

// 計(jì)算服務(wù)實(shí)例權(quán)重的核心方法.
class ServerWeight {

    public void maintainWeights() {
        ILoadBalancer lb = getLoadBalancer();
        if (lb == null) {
            return;
        }
        
        if (!serverWeightAssignmentInProgress.compareAndSet(false,  true))  {
            return; 
        }
        
        try {
            logger.info("Weight adjusting job started");
            AbstractLoadBalancer nlb = (AbstractLoadBalancer) lb;
            LoadBalancerStats stats = nlb.getLoadBalancerStats();
            if (stats == null) {
                // no statistics, nothing to do
                return;
            }
            double totalResponseTime = 0;
            // find maximal 95% response time
            for (Server server : nlb.getAllServers()) {
                // this will automatically load the stats if not in cache
                ServerStats ss = stats.getSingleServerStat(server);
                totalResponseTime += ss.getResponseTimeAvg();
            }
            // weight for each server is (sum of responseTime of all servers - responseTime)
            // so that the longer the response time, the less the weight and the less likely to be chosen
            Double weightSoFar = 0.0;
            
            // create new list and hot swap the reference
            List<Double> finalWeights = new ArrayList<Double>();
            for (Server server : nlb.getAllServers()) {
                ServerStats ss = stats.getSingleServerStat(server);
                double weight = totalResponseTime - ss.getResponseTimeAvg(); // 平均響應(yīng)時間越短,則權(quán)重越大,就越容易被選中.
                weightSoFar += weight;
                finalWeights.add(weightSoFar);   
            }
            setWeights(finalWeights);
        } catch (Exception e) {
            logger.error("Error calculating server weights", e);
        } finally {
            serverWeightAssignmentInProgress.set(false);
        }

    }
}

public Server choose(ILoadBalancer lb, Object key) {

     ...
     
    // 根據(jù)權(quán)重選擇服務(wù)的核心代碼 
    double randomWeight = random.nextDouble() * maxTotalWeight;
    // pick the server index based on the randomIndex
    int n = 0;
    for (Double d : currentWeights) {
        if (d >= randomWeight) {
            serverIndex = n;
            break;
        } else {
            n++;
        }
    }
    
    server = allList.get(serverIndex);
    
    ...
}


}
  • RetryRule

在RoundRobinRule的基礎(chǔ)上,增加了重試的機(jī)制.

  • ZoneAvoidanceRule
使用ZoneAvoidancePredicate和AvailabilityPredicate來判斷是否選擇某個server,前一個判斷判定一個zone的運(yùn)行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于過濾掉連接數(shù)過多的Server。

網(wǎng)頁標(biāo)題:Ribbon之IRule
地址分享:http://muchs.cn/article22/gjscjc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)、網(wǎng)站制作云服務(wù)器、App設(shè)計(jì)營銷型網(wǎng)站建設(shè)、自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司