欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于Java中常見(jiàn)的負(fù)載均衡算法

 更新時(shí)間:2023年08月15日 08:48:27   作者:Dreamlike223  
這篇文章主要介紹了關(guān)于Java中常見(jiàn)的負(fù)載均衡算法,負(fù)載平衡是一種電子計(jì)算機(jī)技術(shù),用來(lái)在多個(gè)計(jì)算機(jī)、網(wǎng)絡(luò)連接、CPU、磁盤(pán)驅(qū)動(dòng)器或其他資源中分配負(fù)載,以達(dá)到優(yōu)化資源使用、最大化吞吐率、最小化響應(yīng)時(shí)間、同時(shí)避免過(guò)載的目的,需要的朋友可以參考下

負(fù)載均衡

在這里插入圖片描述

負(fù)載平衡(Load balancing)是一種電子計(jì)算機(jī)技術(shù),用來(lái)在多個(gè)計(jì)算機(jī)(計(jì)算機(jī)集群)、網(wǎng)絡(luò)連接、CPU、磁盤(pán)驅(qū)動(dòng)器或其他資源中分配負(fù)載,以達(dá)到優(yōu)化資源使用、最大化吞吐率、最小化響應(yīng)時(shí)間、同時(shí)避免過(guò)載的目的。

使用帶有負(fù)載平衡的多個(gè)服務(wù)器組件,取代單一的組件,可以通過(guò)冗余提高可靠性。

負(fù)載平衡服務(wù)通常是由專(zhuān)用軟件和硬件來(lái)完成。

主要作用是將大量作業(yè)合理地分?jǐn)偟蕉鄠€(gè)操作單元上進(jìn)行執(zhí)行,用于解決互聯(lián)網(wǎng)架構(gòu)中的高并發(fā)和高可用的問(wèn)題。

常見(jiàn)的負(fù)載均衡算法

在這里插入圖片描述

1.輪詢(Round Robin)

輪詢算法按照順序?qū)⑿碌恼?qǐng)求分配給下一個(gè)服務(wù)器,最終實(shí)現(xiàn)平分請(qǐng)求。

實(shí)例:已知服務(wù)器: s1 ,s2, s3

請(qǐng)求1 -> s1

請(qǐng)求2-> s2

請(qǐng)求3 -> s3

請(qǐng)求4 -> s1

請(qǐng)求5 -> s2

請(qǐng)求6 -> s3

優(yōu)點(diǎn):

  • ? 實(shí)現(xiàn)簡(jiǎn)單,無(wú)需記錄各種服務(wù)的狀態(tài),是一種無(wú)狀態(tài)的負(fù)載均衡策略。
  • ? 實(shí)現(xiàn)絕對(duì)公平

缺點(diǎn):

  • 當(dāng)各個(gè)服務(wù)器性能不一致的情況,無(wú)法根據(jù)服務(wù)器性能去分配,無(wú)法合理利用服務(wù)器資源。

java實(shí)現(xiàn)輪詢算法:

思路:根據(jù)上面的介紹,依次的選擇下一個(gè)服務(wù)器,輪詢算法具有周期性的特性,這就是典型的周期性概念,我們第一想法應(yīng)該就是取余了。

這里推薦大家《程序員的數(shù)學(xué)1》里面介紹了一些數(shù)學(xué)和編程思維的一些案例,其中就有介紹周期和分組的思想,個(gè)人感覺(jué)這本書(shū)還是不錯(cuò)的,推薦給大家。

public class RoundRobin {
    @Data
    public static class Server {
        private int serverId;
        private String name;
        private int weight;
        public Server(int serverId, String name) {
            this.serverId = serverId;
            this.name = name;
        }
        public Server(int serverId, String name, int weight) {
            this.serverId = serverId;
            this.name = name;
            this.weight = weight;
        }
    }
    private static AtomicInteger NEXT_SERVER_COUNTER = new AtomicInteger(0);
    private static int select(int modulo) {
        for (; ; ) {
            int current = NEXT_SERVER_COUNTER.get();
            int next = (current + 1) % modulo;
            boolean compareAndSet = NEXT_SERVER_COUNTER.compareAndSet(current, next);
            if (compareAndSet) {
                return next;
            }
        }
    }
    public static Server selectServer(List<Server> serverList) {
        return serverList.get(select(serverList.size()));
    }
    public static void main(String[] args) {
        List<Server> serverList = new ArrayList<>();
        serverList.add(new Server(1, "服務(wù)器1"));
        serverList.add(new Server(2, "服務(wù)器2"));
        serverList.add(new Server(3, "服務(wù)器3"));
        for (int i = 0; i < 10; i++) {
            Server selectedServer = selectServer(serverList);
            System.out.format("第%d次請(qǐng)求,選擇服務(wù)器%s\n", i + 1, selectedServer.toString());
        }
    }
}

在這里插入圖片描述

2.加權(quán)輪詢(WeightedRound-Robin)

由于不同的服務(wù)器配置不同,因此它們處理請(qǐng)求的能力也不同,給配置高的機(jī)器配置相對(duì)較高的權(quán)重,讓其處理更多的請(qǐng)求,給配置較低的機(jī)器配置較低的權(quán)重減輕期負(fù)載壓力。

加權(quán)輪詢可以較好的解決這個(gè)問(wèn)題。

思路:

根據(jù)權(quán)重的大小讓其獲得相應(yīng)被輪詢到的機(jī)會(huì)。

已知:

服務(wù)器權(quán)重
s11
s22
s33

可以根據(jù)權(quán)重我們?cè)趦?nèi)存中創(chuàng)建一個(gè)這樣的數(shù)組{s1,s2,s2,s3,s3,s3},然后再按照輪詢的方式選擇相應(yīng)的服務(wù)器。

缺點(diǎn):

  • 請(qǐng)求被分配到三臺(tái)服務(wù)器上機(jī)會(huì)不夠平滑。
  • 前3次請(qǐng)求都不會(huì)落在server3上。

Nginx實(shí)現(xiàn)了一種平滑的加權(quán)輪詢算法,可以將請(qǐng)求平滑(均勻)的分配到各個(gè)節(jié)點(diǎn)上。

下面我們用Java實(shí)現(xiàn)一下這個(gè)算法。

實(shí)現(xiàn)思路

我們以當(dāng)前節(jié)點(diǎn)權(quán)重作為被選中的概率

 public void incrCurrentWeight() {
      this.currentWeight += weight;
 }

為了避免權(quán)重大的被連續(xù)選中,所以再被選中的時(shí)候我們應(yīng)該讓其的當(dāng)前權(quán)重變小。我們可以采用

//當(dāng)前權(quán)重 = 當(dāng)前權(quán)重 - 總權(quán)重

1-6 =-5

3-6 =-3

可得權(quán)重越大下次當(dāng)前權(quán)重變成最大的可能性也越大

public void selected(int total) {
    this.currentWeight -= total;
}

我們選取當(dāng)前當(dāng)前權(quán)重最大的一個(gè)服務(wù)器

public class WeightRoundRobin {
    @Data
    public static class Server {
        private int serverId;
        private String name;
        private int weight;
        private int currentWeight;
        public Server(int serverId, String name) {
            this.serverId = serverId;
            this.name = name;
        }
        public Server(int serverId, String name, int weight) {
            this.serverId = serverId;
            this.name = name;
            this.weight = weight;
        }
        public void selected(int total) {
            this.currentWeight -= total;
        }
        public void incrCurrentWeight() {
            this.currentWeight += weight;
        }
    }
    public static Server selectServer(List<Server> serverList) {
        int total = 0;
        Server selectedServer = null;
        int maxWeight = 0;
        for (Server server : serverList) {
            total += server.getWeight();
            server.incrCurrentWeight();
          	//選取當(dāng)前權(quán)重最大的一個(gè)服務(wù)器
            if (selectedServer == null || maxWeight < server.getCurrentWeight()) {
                selectedServer = server;
                maxWeight = server.getCurrentWeight();
            }
        }
        if (selectedServer == null){
            Random random = new Random();
            int next = random.nextInt(serverList.size());
            return serverList.get(next);
        }
        selectedServer.selected(total);
        return selectedServer;
    }
    public static void main(String[] args) {
        List<Server> serverList = new ArrayList<>();
        serverList.add(new Server(1, "服務(wù)器1", 1));
        serverList.add(new Server(2, "服務(wù)器2", 3));
        serverList.add(new Server(3, "服務(wù)器3", 10));
        for (int i = 0; i < 10; i++) {
            Server server = selectServer(serverList);
            System.out.format("第%d次請(qǐng)求,選擇服務(wù)器%s\n", i + 1, server.toString());
        }
    }

在這里插入圖片描述

3.隨機(jī)(Random)

思路:利用隨機(jī)數(shù)從所有服務(wù)器中隨機(jī)選取一臺(tái),可以用服務(wù)器數(shù)組下標(biāo)獲取。

public class RandomLoadBalance {
    @Data
    public static class Server {
        private int serverId;
        private String name;
        private int weight;
        public Server(int serverId, String name) {
            this.serverId = serverId;
            this.name = name;
        }
    }
    public static Server selectServer(List<Server> serverList) {
        Random selector = new Random();
        int next = selector.nextInt(serverList.size());
        return serverList.get(next);
    }
    public static void main(String[] args) {
        List<Server> serverList = new ArrayList<>();
        serverList.add(new Server(1, "服務(wù)器1"));
        serverList.add(new Server(2, "服務(wù)器2"));
        serverList.add(new Server(3, "服務(wù)器3"));
        for (int i = 0; i < 10; i++) {
            Server selectedServer = selectServer(serverList);
            System.out.format("第%d次請(qǐng)求,選擇服務(wù)器%s\n", i + 1, selectedServer.toString());
        }
    }
}

在這里插入圖片描述

4.加權(quán)隨機(jī)(Weight Random)

思路:

這里我們是利用區(qū)間的思想,通過(guò)一個(gè)小于在此區(qū)間范圍內(nèi)的一個(gè)隨機(jī)數(shù),選中對(duì)應(yīng)的區(qū)間(服務(wù)器),區(qū)間越大被選中的概率就越大。

已知:

服務(wù)器權(quán)重
s11
s22
s33

那么: 

s1:[0,1]
s2:(1,3]
s3 (3,6]
public class WeightRandom {
    @Data
    public static class Server {
        private int serverId;
        private String name;
        private int weight;
        public Server(int serverId, String name) {
            this.serverId = serverId;
            this.name = name;
        }
        public Server(int serverId, String name, int weight) {
            this.serverId = serverId;
            this.name = name;
            this.weight = weight;
        }
    }
    private static Server selectServer(List<Server> serverList) {
        int sumWeight = 0;
        for (Server server : serverList) {
            sumWeight += server.getWeight();
        }
        Random serverSelector = new Random();
        int nextServerRange = serverSelector.nextInt(sumWeight);
        int sum = 0;
        Server selectedServer = null;
        for (Server server : serverList) {
            if (nextServerRange >= sum && nextServerRange < server.getWeight() + sum) {
                selectedServer = server;
            }
            sum += server.getWeight();
        }
        return selectedServer;
    }
    public static void main(String[] args) {
        List<Server> serverList = new ArrayList<>();
        serverList.add(new Server(1, "服務(wù)器1", 1));
        serverList.add(new Server(2, "服務(wù)器2", 5));
        serverList.add(new Server(3, "服務(wù)器3", 10));
        for (int i = 0; i < 10; i++) {
            Server selectedServer = selectServer(serverList);
            System.out.format("第%d次請(qǐng)求,選擇服務(wù)器%s\n", i + 1, selectedServer.toString());
        }
    }
}

在這里插入圖片描述

5.IPHash

思路:根據(jù)每個(gè)每個(gè)請(qǐng)求ip(也可以是某個(gè)標(biāo)識(shí))ip.hash() % server.size()

public class IpHash {
    @Data
    public static class Server {
        private int serverId;
        private String name;
        public Server(int serverId, String name) {
            this.serverId = serverId;
            this.name = name;
        }
    }
    public static Server selectServer(List<Server> serverList, String ip) {
        int ipHash = ip.hashCode();
        return serverList.get(ipHash % serverList.size());
    }
    public static void main(String[] args) {
        List<Server> serverList = new ArrayList<>();
        serverList.add(new Server(1, "服務(wù)器1"));
        serverList.add(new Server(2, "服務(wù)器2"));
        serverList.add(new Server(3, "服務(wù)器3"));
        List<String> ips = Arrays.asList("192.168.9.5", "192.168.9.2", "192.168.9.3");
        for (int i = 0; i < 10; i++) {
            for (String ip : ips) {
                Server selectedServer = selectServer(serverList, ip);
                System.out.format("請(qǐng)求ip:%s,選擇服務(wù)器%s\n", ip, selectedServer.toString());
            }
        }
    }
}

在這里插入圖片描述

可以看到結(jié)果:同一ip肯定會(huì)命中同一臺(tái)機(jī)器。

到此這篇關(guān)于關(guān)于Java中常見(jiàn)的負(fù)載均衡算法的文章就介紹到這了,更多相關(guān)Java負(fù)載均衡算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論