最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Java實現(xiàn)6種常見負載均衡算法

 更新時間:2023年06月12日 08:43:30   作者:Cosolar  
Java負載均衡算法也是分布式系統(tǒng)中的重要組成部分,用于將來自客戶端的請求分配到不同的后端服務器上,本文將介紹常見的Java負載均衡算法,輪詢法、加權(quán)隨機法……一次性讓你了解?6?種常見負載均衡算法

負載均衡是指將來自客戶端的請求分攤到多個服務器上進行處理,從而有效地提高系統(tǒng)性能、可用性和可擴展性。常見的負載均衡算法包括輪詢法、加權(quán)輪詢法、隨機法、加權(quán)隨機法、源地址哈希法和最小連接數(shù)法等。

在實際應用中有很多工具和框架使用了這些算法來解決服務器負載均衡的問題。下面我整理出了一些常見的工具和框架:

  • Nginx:Nginx 是一款高性能的 Web 服務器,同時也是一款反向代理服務器。Nginx 的負載均衡模塊支持多種算法,包括輪詢法、加權(quán)輪詢法、IP_HASH 等。

  • Apache:Apache 是一款流行的 Web 服務器。Apache 也提供了負載均衡模塊,支持多種算法,包括輪詢法、加權(quán)輪詢法、最小連接數(shù)法等。

  • HAProxy:HAProxy 是一款高性能的 TCP/HTTP 負載均衡器,支持多種負載均衡算法,包括輪詢法、加權(quán)輪詢法、IP_HASH、最少連接數(shù)法、最短響應時間法等。

  • Spring Cloud Ribbon:Ribbon 是一款基于 HTTP 和 TCP 客戶端的負載均衡器,是 Spring Cloud 生態(tài)系統(tǒng)中的一員。Ribbon 支持多種負載均衡算法,包括輪詢法、加權(quán)輪詢法、隨機法等。

  • ZooKeeper:ZooKeeper 是一款分布式協(xié)調(diào)服務,在分布式系統(tǒng)中廣泛應用。ZooKeeper 的客戶端庫 Curator 提供了一種基于 ZooKeeper 的負載均衡算法,稱為 Dynamic Server List Load Balancing。

這些工具和框架都應用了負載均衡算法來實現(xiàn)服務器的負載均衡,它們的實現(xiàn)方式也各不相同,但是盡管如此,我們可以從中學習到很多有價值的經(jīng)驗和思路。

劃重點 Java 架構(gòu)師必備技能-我們要深入學習各類負載均衡算法實現(xiàn)方式

Java負載均衡算法也是分布式系統(tǒng)中的重要組成部分,用于將來自客戶端的請求分配到不同的后端服務器上,以達到提高系統(tǒng)吞吐量、減輕服務器負擔、提高系統(tǒng)可用性等目的。本文將介紹常見的Java負載均衡算法,輪詢法、加權(quán)隨機法……一次性讓你了解 6 種常見負載均衡算法。

一、輪詢法(Round Robin)

輪詢法是最簡單、最常見的負載均衡算法之一,其實現(xiàn)思路也非常簡單:按照事先規(guī)定的順序依次將請求轉(zhuǎn)發(fā)至后端服務器。例如,若有3臺服務器,則第1個請求會被分配到第1臺服務器上,第2個請求會被分配到第2臺服務器上,第3個請求會被分配到第3臺服務器上,第4個請求又會被分配到第1臺服務器上,以此類推。

這種算法的優(yōu)點是實現(xiàn)簡單、可靠性高,但是它并沒有考慮服務器的實際負載情況,導致某些服務器可能會承受過多的負載,而其他服務器則處于空閑狀態(tài)。

輪詢法(Round Robin)寫個簡單的實現(xiàn)代碼讓你感覺一下:

//定義一個全局計數(shù)器,每次調(diào)用累加
private static AtomicInteger atomicInteger = new AtomicInteger(0);
//定義服務器列表
private static List<String> serverList = new ArrayList<>();
public static String roundRobin() {
    //獲取服務器數(shù)量
    int serverCount = serverList.size();
    //獲取當前請求應該轉(zhuǎn)發(fā)到哪臺服務器
    int currentServerIndex = atomicInteger.incrementAndGet() % serverCount;
    //返回對應的服務器地址
    return serverList.get(currentServerIndex);
}

二、加權(quán)輪詢法(Weight Round Robin)

加權(quán)輪詢法是在輪詢法的基礎(chǔ)上進行改進,其思路是在服務器的選擇中,根據(jù)服務器的處理能力或負載情況分配不同的權(quán)重,以使處理能力較強或負載較輕的服務器獲得更多的請求。例如,若存在2臺服務器,其中第1臺服務器負載比較重,則應當將更多的請求分配給第2臺服務器。

舉個例子,如果服務器A的權(quán)重是2,服務器B的權(quán)重是1,那么在兩個請求中,有一個請求會被發(fā)送到服務器A,另一個請求將被發(fā)送到服務器B。

這種算法的優(yōu)點是可以根據(jù)服務器的實際負載情況來分配請求,但是還是存在服務器負載不均衡的問題,因為它只是根據(jù)權(quán)值進行分配,并沒有考慮服務器的實際負載情況。

加權(quán)輪詢法按自己的思路寫一下如下示例:

//定義一個全局計數(shù)器,每次調(diào)用累加
private static AtomicInteger atomicInteger = new AtomicInteger(0);
//定義服務器列表及服務器權(quán)重值
private static Map<String, Integer> serverMap = new ConcurrentHashMap<>();
//記錄服務器權(quán)重總和
private static int totalWeight = 0;
public static String weightRoundRobin() {
    //獲取服務器數(shù)量
    int serverCount = serverMap.size();
    //如果沒有可用的服務器返回null
    if (serverCount == 0) {
        return null;
    }
    //在此處為避免多線程并發(fā)操作造成錯誤,在方法內(nèi)部進行鎖操作
    synchronized (serverMap) {
        //計算服務器權(quán)重總和
        for (Map.Entry<String, Integer> entry : serverMap.entrySet()) {
            totalWeight += entry.getValue();
        }
        //獲取當前請求應該轉(zhuǎn)發(fā)到哪臺服務器
        int currentServerIndex = atomicInteger.incrementAndGet() % totalWeight;
        //遍歷服務器列表,根據(jù)服務器權(quán)重值選擇對應地址
        for (Map.Entry<String, Integer> entry : serverMap.entrySet()) {
            String serverAddress = entry.getKey();
            Integer weight = entry.getValue();
            currentServerIndex -= weight;
            if (currentServerIndex < 0) {
                return serverAddress;
            }
        }
    }
    //默認返回null
    return null;
}

這是源碼中的一個小小的摘抄,供你觀賞一下:

public class WeightRoundRobinLoadBalancer implements LoadBalancer {
    private List<String> servers = new ArrayList<>();
    private Map<String, Integer> weightMap = new HashMap<>();
    private int currentWeightIndex = -1;
    public WeightRoundRobinLoadBalancer(Map<String, Integer> servers) {
        this.servers.addAll(servers.keySet());
        for (String server : servers.keySet()) {
            int weight = servers.get(server);
            weightMap.put(server, weight);
        }
    }
    @Override
    public synchronized String chooseServer() {
        int weightSum = weightMap.values().stream().reduce(Integer::sum).orElse(0);
        while (true) {
            currentWeightIndex = (currentWeightIndex + 1) % servers.size();
            String server = servers.get(currentWeightIndex);
            int weight = weightMap.get(server);
            if (weight >= weightSum) {
                return server;
            }
            weightSum -= weight;
        }
    }
}

三、隨機法(Random)

隨機法是指將請求隨機分配至后端服務器的負載均衡算法。該算法實現(xiàn)簡單,但分配效果不可控,難以保證后端服務器的負載均衡。因此,隨機法通常被用作測試或壓力測試等臨時場景下的負載均衡算法。

隨機法實現(xiàn)代碼如下:

// 1、思路參考:-----------------------------------------------
//定義服務器列表
private static List<String> serverList = new ArrayList<>();
public static String random() {
    //獲取服務器數(shù)量
    int serverCount = serverList.size();
    //如果沒有可用的服務器返回null
    if (serverCount == 0) {
        return null;
    }
    //生成一個隨機數(shù)
    int randomIndex = new Random().nextInt(serverCount);
    //返回對應的服務器地址
    return serverList.get(randomIndex);
}
// 2、源碼參考:-----------------------------------------------
public class RandomLoadBalancer implements LoadBalancer {
    private List<String> servers = new ArrayList<>();
    public RandomLoadBalancer(List<String> servers) {
        this.servers = servers;
    }
    @Override
    public String chooseServer() {
        int randomIndex = ThreadLocalRandom.current().nextInt(servers.size());
        return servers.get(randomIndex);
    }
}

四、加權(quán)隨機法(Weight Random)

加權(quán)隨機法是在隨機法的基礎(chǔ)上進行改進,其思路是在服務器的選擇中,根據(jù)服務器的處理能力或負載情況分配不同的權(quán)重,以使處理能力較強或負載較輕的服務器獲得更多的請求。

加權(quán)隨機法實現(xiàn)代碼如下:

// 1、思路參考:-----------------------------------------------------------
//定義服務器列表及服務器權(quán)重值
private static Map<String, Integer> serverMap = new ConcurrentHashMap<>();
//記錄服務器權(quán)重總和
private static int totalWeight = 0;
public static String weightRandom() {
    //獲取服務器數(shù)量
    int serverCount = serverMap.size();
    //如果沒有可用的服務器返回null
    if (serverCount == 0) {
        return null;
    }
    //在此處為避免多線程并發(fā)操作造成錯誤,在方法內(nèi)部進行鎖操作
    synchronized (serverMap) {
        //計算服務器權(quán)重總和
        for (Map.Entry<String, Integer> entry : serverMap.entrySet()) {
            totalWeight += entry.getValue();
        }
        //生成一個隨機數(shù)
        int randomWeight = new Random().nextInt(totalWeight);
        //遍歷服務器列表,根據(jù)服務器權(quán)重值選擇對應地址
        for (Map.Entry<String, Integer> entry : serverMap.entrySet()) {
            String serverAddress = entry.getKey();
            Integer weight = entry.getValue();
            randomWeight -= weight;
            if (randomWeight < 0) {
                return serverAddress;
            }
        }
    }
    //默認返回null
    return null;
}
// 2、源碼參考:-----------------------------------------------------------
public class WeightRandomLoadBalancer implements LoadBalancer {
    private List<String> servers = new ArrayList<>();
    private Map<String, Integer> weightMap = new HashMap<>();
    public WeightRandomLoadBalancer(Map<String, Integer> servers) {
        this.servers.addAll(servers.keySet());
        for (String server : servers.keySet()) {
            int weight = servers.get(server);
            weightMap.put(server, weight);
        }
    }
    @Override
    public String chooseServer() {
        int weightSum = weightMap.values().stream().reduce(Integer::sum).orElse(0);
        int randomWeight = ThreadLocalRandom.current().nextInt(weightSum) + 1;
        for (String server : servers) {
            int weight = weightMap.get(server);
            if (randomWeight <= weight) {
                return server;
            }
            randomWeight -= weight;
        }
        return null;
    }
}

五、源地址哈希法(Hash)

源地址哈希法是一種基于請求源IP地址的負載均衡算法,其思路是將每個請求的源IP地址通過哈希函數(shù)計算出一個值,然后根據(jù)該值與可用服務器總數(shù)取模的結(jié)果來確定該請求應當轉(zhuǎn)發(fā)到哪臺服務器上。

換言之,源地址哈希算法就是使用客戶端 IP 地址作為哈希鍵。負載均衡器將哈希值映射到可用服務器中的一個,然后將請求發(fā)送到這個服務器處理。如果客戶端 IP 地址發(fā)生改變(比如重啟后重新分配 IP 地址),那么將會被分配到其他服務器上。

這種算法的優(yōu)點是可以避免某些客戶端被重定向到不同的服務器,對于同一IP地址的請求,總是會被分配到同一臺服務器上,因此可以在一定程度上提高緩存命中率等性能指標,但是它也有一些缺點。例如,如果有很多請求來自相同的 IP 地址,那么可能會導致某個服務器負載過高。另外,由于服務器數(shù)量的變化,哈希值映射也會發(fā)生變化,這可能會導致緩存無效,并且需要重新分配所有請求。

源地址哈希法實現(xiàn)代碼示例如下:

// 1、思路參考:-----------------------------------------------------------
//定義服務器列表
private static List<String> serverList = new ArrayList<>();
public static String hash(String clientIP) {
    //獲取服務器數(shù)量
    int serverCount = serverList.size();
    //如果沒有可用的服務器返回null
    if (serverCount == 0) {
        return null;
    }
    //將客戶端IP地址進行哈希計算
    int hashCode = clientIP.hashCode();
    //根據(jù)哈希值計算需要轉(zhuǎn)發(fā)到哪臺服務器上
    int serverIndex = hashCode % serverCount;
    //返回對應的服務器地址
    return serverList.get(serverIndex);
}
// 2、源碼參考:-----------------------------------------------------------
public class HashLoadBalancer implements LoadBalancer {
    private List<String> servers = new ArrayList<>();
    public HashLoadBalancer(List<String> servers) {
        this.servers = servers;
    }
    @Override
    public String chooseServer() {
        String clientIp = getClientIp();
        int hashCode = Math.abs(clientIp.hashCode());
        return servers.get(hashCode % servers.size());
    }
    private String getClientIp() {
        // 獲取客戶端IP地址的代碼省略
        return "1.1.1.1";
    }
}

六、最小連接數(shù)法(Least Connections)

最小連接數(shù)法是一種動態(tài)調(diào)整的負載均衡算法,其思路是盡可能地將請求分配給當前空閑連接數(shù)最少的后端服務器,以達到負載均衡的效果。在實現(xiàn)過程中,通常需要定期檢測各個服務器的連接數(shù)并進行動態(tài)調(diào)整。

最小連接數(shù)算法是根據(jù)當前連接數(shù)來選擇一個可用服務器。負載均衡器會查詢可用服務器的連接數(shù),然后選擇一個連接數(shù)最小的服務器。這種算法保證了服務器不會被過度負載,并且還允許負載均衡器根據(jù)實際情況動態(tài)分配請求。

需要注意的是,如果服務器掛掉了或者網(wǎng)絡鏈路中斷了,那么負載均衡器就需要重新計算服務器的連接數(shù),這將延長響應時間并且影響性能。

最小連接數(shù)法實現(xiàn)代碼示例如下:

// 1、思路參考:-----------------------------------------------------------
//定義服務器列表
private static List<String> serverList = new ArrayList<>();
//記錄每個服務器的連接數(shù)
private static Map<String, Integer> connectionsMap = new ConcurrentHashMap<>();
public static String leastConnections() {
    //獲取服務器數(shù)量
    int serverCount = serverList.size();
    //如果沒有可用的服務器返回null
    if (serverCount == 0) {
        return null;
    }
    //默認選擇第一個服務器
    String selectedServerAddress = serverList.get(0);
    //獲取第一個服務器的連接數(shù)
    int minConnections = connectionsMap.getOrDefault(selectedServerAddress, 0);
    //遍歷服務器列表,尋找連接數(shù)最少的服務器
    for (int i = 1; i < serverCount; i++) {
        String serverAddress = serverList.get(i);
        int connections = connectionsMap.getOrDefault(serverAddress, 0);
        if (connections < minConnections) {
            selectedServerAddress = serverAddress;
            minConnections = connections;
        }
    }
    //返回連接數(shù)最少的服務器地址
    return selectedServerAddress;
}
// 2、源碼參考:-----------------------------------------------------------
public class LeastConnectionsLoadBalancer implements LoadBalancer {
    private List<String> servers = new ArrayList<>();
    private Map<String, Integer> connectionsMap = new HashMap<>();
    public LeastConnectionsLoadBalancer(List<String> servers) {
        this.servers = servers;
        for (String server : servers) {
            connectionsMap.put(server, 0);
        }
    }
    @Override
    public synchronized String chooseServer() {
        int minConnections = Integer.MAX_VALUE;
        String targetServer = null;
        for (String server : servers) {
            int connections = connectionsMap.get(server);
            if (connections < minConnections) {
                minConnections = connections;
                targetServer = server;
            }
        }
        connectionsMap.put(targetServer, connectionsMap.get(targetServer) + 1);
        return targetServer;
    }
    public void releaseConnection(String server) {
        connectionsMap.put(server, connectionsMap.get(server) - 1);
    }
}

以上便是常見的Java負載均衡算法,這些算法都有其自身的優(yōu)缺點和適用場景。

七、小結(jié)一下

Java 架構(gòu)師面臨的挑戰(zhàn)越來越大,我們需要在不斷發(fā)展的技術(shù)中保持敏銳的觸覺,并掌握越來越廣泛的知識。而在當前互聯(lián)網(wǎng)架構(gòu)中,負載均衡算法是一個至關(guān)重要的領(lǐng)域。它是實現(xiàn)服務的高可用性和可伸縮性的重要手段。因此,Java 架構(gòu)師必須深入學習各類負載均衡算法的實現(xiàn)方式,并且理解它們的優(yōu)劣之處,以便為公司設計出更好的網(wǎng)絡架構(gòu)。

如果你想成為一名 Java 架構(gòu)師或者網(wǎng)絡工程師,那么希望你多多了解底層知識對你將大有益處。讓我們一起努力吧!

以上就是使用Java實現(xiàn)6種常見負載均衡算法的詳細內(nèi)容,更多關(guān)于Java 負載均衡的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Springboot整合Shiro之加鹽MD5加密的方法

    Springboot整合Shiro之加鹽MD5加密的方法

    這篇文章主要介紹了Springboot整合Shiro之加鹽MD5加密的方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-12-12
  • RocketMQ消息拉取過程詳解

    RocketMQ消息拉取過程詳解

    這篇文章主要為大家介紹了RocketMQ消息拉取過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • JAVA 數(shù)據(jù)結(jié)構(gòu)之Queue處理實例代碼

    JAVA 數(shù)據(jù)結(jié)構(gòu)之Queue處理實例代碼

    這篇文章主要介紹了JAVA 數(shù)據(jù)結(jié)構(gòu)之Queue處理實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Java中Stream流中map和forEach的區(qū)別詳解

    Java中Stream流中map和forEach的區(qū)別詳解

    本文主要介紹了Java中Stream流中map和forEach的區(qū)別詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-04-04
  • MyBatis注解式開發(fā)映射語句詳解

    MyBatis注解式開發(fā)映射語句詳解

    這幾年來注解開發(fā)越來越流行,Mybatis也可以使用注解開發(fā)方式,這樣我們就可以減少編寫Mapper映射文件了。我們先圍繞一些基本的CRUD來學習,再學習復雜映射多表操作
    2023-02-02
  • MyBatis持久層框架的用法知識小結(jié)

    MyBatis持久層框架的用法知識小結(jié)

    MyBatis 本是apache的一個開源項目iBatis,接下來通過本文給大家介紹MyBatis持久層框架的用法知識小結(jié),非常不錯,具有參考借鑒價值,感興趣的朋友一起學習吧
    2016-07-07
  • 使用spring-data-jpa實現(xiàn)簡單的兩表聯(lián)查實踐

    使用spring-data-jpa實現(xiàn)簡單的兩表聯(lián)查實踐

    本文介紹了Spring Data JPA在Spring Boot中的配置與簡單操作,涵蓋一對多和多對一關(guān)系的處理,適合初學者學習,通過配置數(shù)據(jù)源、創(chuàng)建實體類和DAO接口,實現(xiàn)基本的CRUD操作,并提供了一個簡單的示例
    2026-06-06
  • 詳解Java編程中統(tǒng)一資源定位符URL的相關(guān)使用

    詳解Java編程中統(tǒng)一資源定位符URL的相關(guān)使用

    這篇文章主要介紹了Java編程中統(tǒng)一資源定位符URL的相關(guān)使用,是Java網(wǎng)絡編程中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-10-10
  • Java?HashMap的底層實現(xiàn)原理深度解析

    Java?HashMap的底層實現(xiàn)原理深度解析

    HashMap基于數(shù)組+鏈表+紅黑樹結(jié)構(gòu),通過哈希算法和擴容機制優(yōu)化性能,負載因子與樹化閾值平衡效率,是Java開發(fā)必備的高效數(shù)據(jù)結(jié)構(gòu),本文給大家介紹Java?HashMap的底層實現(xiàn)原理,感興趣的朋友一起看看吧
    2025-09-09
  • Eclipse配置python開發(fā)環(huán)境過程圖解

    Eclipse配置python開發(fā)環(huán)境過程圖解

    這篇文章主要介紹了Eclipse配置python開發(fā)環(huán)境過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03

最新評論

大港区| 永清县| 东宁县| 稻城县| 溆浦县| 廉江市| 游戏| 广南县| 屯门区| 政和县| 蓬安县| 鹿邑县| 原阳县| 象州县| 祥云县| 潮州市| 玉树县| 威宁| 滦平县| 临泽县| 门源| 额济纳旗| 博乐市| 延庆县| 绵阳市| 华亭县| 高安市| 沿河| 子长县| 泸西县| 岳池县| 盘山县| 沙河市| 贵德县| 兴文县| 互助| 聊城市| 西丰县| 高唐县| 凤冈县| 濮阳县|