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

從零帶你手寫Java七種負載均衡算法實現(xiàn)方案

 更新時間:2026年02月13日 09:27:35   作者:大黃評測  
在分布式系統(tǒng),微服務架構(gòu)以及高并發(fā)場景中,負載均衡是一項至關(guān)重要的技術(shù)本文將帶你純手寫實現(xiàn)七種常見的負載均衡算法,全部使用?Java?編寫,不依賴任何第三方框架,幫助你深入理解其核心原理與適用場景

在分布式系統(tǒng)、微服務架構(gòu)以及高并發(fā)場景中,負載均衡(Load Balancing) 是一項至關(guān)重要的技術(shù)。它能夠?qū)⒄埱蠛侠淼胤职l(fā)到多個服務節(jié)點上,從而提升系統(tǒng)整體的吞吐量、可用性和容錯能力。

本文將帶你純手擼實現(xiàn)七種常見的負載均衡算法,全部使用 Java 編寫,不依賴任何第三方框架,幫助你深入理解其核心原理與適用場景。

準備工作

首先定義一個通用的服務節(jié)點接口:

public class Server {
    private String host;
    private int port;
    private int weight; // 權(quán)重,用于加權(quán)類算法

    public Server(String host, int port) {
        this(host, port, 1);
    }

    public Server(String ??host, int port, int weight) {
        this.host = host;
        this.port = port;
        this.weight = weight;
    }

    // getters & setters
    public String getHost() { return host; }
    public int getPort() { return port; }
    public int getWeight() { return weight; }
    public void setWeight(int weight) { this.weight = weight; }

    @Override
    public String toString() {
        return host + ":" + port + "(w=" + weight + ")";
    }
}

所有算法都將實現(xiàn)以下接口:

public interface LoadBalancer {
    Server select(List<Server> servers);
}

1. 隨機(Random)

最簡單的策略:從可用節(jié)點中隨機選擇一個。

public class RandomLoadBalancer implements LoadBalancer {
    private final Random random = new Random();

    @Override
    public Server select(List<Server> servers) {
        if (servers == null || servers.isEmpty()) return null;
        int index = random.nextInt(servers.size());
        return servers.get(index);
    }
}

優(yōu)點:簡單、無狀態(tài)

缺點:無法保證請求分布均勻(尤其在短時間窗口內(nèi))

2. 輪詢(Round Robin)

按順序依次選擇節(jié)點,循環(huán)往復。

public class RoundRobinLoadBalancer implements LoadBalancer {
    private AtomicInteger index = new AtomicInteger(0);

    @Override
    public Server select(List<Server> servers) {
        if (servers == null || servers.isEmpty()) return null;
        int i = index.getAndIncrement() % servers.size();
        // 處理負數(shù)(雖然 unlikely)
        if (i < 0) i += servers.size();
        return servers.get(i);
    }
}

優(yōu)點:請求分布均勻

缺點:未考慮服務器性能差異

3. 加權(quán)輪詢(Weighted Round Robin)

為每個節(jié)點分配權(quán)重,高權(quán)重節(jié)點被選中的頻率更高。

實現(xiàn)思路:采用“最大公約數(shù) + 當前輪次”方式,避免預生成列表(節(jié)省內(nèi)存)。

public class WeightedRoundRobinLoadBalancer implements LoadBalancer {
    private AtomicInteger currentPos = new AtomicInteger(0);

    @Override
    public Server select(List<Server> servers) {
        if (servers == null || servers.isEmpty()) return null;

        // 計算總權(quán)重
        int totalWeight = servers.stream().mapToInt(Server::getWeight).sum();
        if (totalWeight <= 0) {
            // 退化為普通輪詢
            return new RoundRobinLoadBalancer().select(servers);
        }

        int current = currentPos.getAndIncrement() % totalWeight;
        if (current < 0) current += totalWeight;

        // 遍歷找到對應節(jié)點
        for (Server server : servers) {
            if (current < server.getWeight()) {
                return server;
            }
            current -= server.getWeight();
        }

        // 理論上不會走到這里
        return servers.get(servers.size() - 1);
    }
}

注意:上述實現(xiàn)是簡化版。工業(yè)級實現(xiàn)(如 Nginx)通常使用更復雜的平滑加權(quán)輪詢(Smooth Weighted Round Robin),以避免連續(xù)選中高權(quán)重節(jié)點。

4. 平滑加權(quán)輪詢(Smooth Weighted Round Robin)

由 Nginx 提出,解決加權(quán)輪詢中“高權(quán)重節(jié)點連續(xù)被選中”的問題。

public class SmoothWeightedRoundRobinLoadBalancer implements LoadBalancer {

    private final Map<Server, Integer> currentWeights = new ConcurrentHashMap<>();

    @Override
    public Server select(List<Server> servers) {
        if (servers == null || servers.isEmpty()) return null;

        int totalWeight = 0;
        Server best = null;
        int max = Integer.MIN_VALUE;

        for (Server server : servers) {
            int weight = server.getWeight();
            if (weight <= 0) weight = 1;

            totalWeight += weight;
            int current = currentWeights.getOrDefault(server, 0) + weight;
            currentWeights.put(server, current);

            if (current > max) {
                max = current;
                best = server;
            }
        }

        if (best != null) {
            currentWeights.put(best, max - totalWeight);
        }

        return best;
    }
}

優(yōu)點:權(quán)重分配更平滑,高權(quán)重節(jié)點不會連續(xù)被選中

示例:A(w=5), B(w=1) → 順序為 A,A,A,A,A,B,... 而非 A,A,A,A,A,A,...

5. 最少連接(Least Connections)

將請求分發(fā)給當前連接數(shù)最少的節(jié)點。

為簡化,我們用一個 Map<Server, AtomicInteger> 模擬連接計數(shù)。

public class LeastConnectionsLoadBalancer implements LoadBalancer {
    private final Map<Server, AtomicInteger> connectionCounts = new ConcurrentHashMap<>();

    @Override
    public Server select(List<Server> servers) {
        if (servers == null || servers.isEmpty()) return null;

        Server best = null;
        int minConn = Integer.MAX_VALUE;

        for (Server server : servers) {
            int conn = connectionCounts.computeIfAbsent(server, k -> new AtomicInteger(0)).get();
            if (conn < minConn) {
                minConn = conn;
                best = server;
            }
        }

        // 模擬增加連接(實際使用需配合請求完成后的 decrement)
        if (best != null) {
            connectionCounts.get(best).incrementAndGet();
        }

        return best;
    }

    // 供外部調(diào)用:請求完成后減少連接數(shù)
    public void release(Server server) {
        AtomicInteger count = connectionCounts.get(server);
        if (count != null) {
            count.decrementAndGet();
        }
    }
}

適用于長連接或處理時間差異大的場景

需要維護連接狀態(tài),有額外開銷

6. 源地址哈希(IP Hash / Source Hash)

根據(jù)客戶端 IP(或其他唯一標識)做哈希,保證同一客戶端始終路由到同一節(jié)點。

public class SourceHashLoadBalancer implements LoadBalancer {
    private String source; // 可通過構(gòu)造函數(shù)傳入 client IP

    public SourceHashLoadBalancer(String source) {
        this.source = source;
    }

    @Override
    public Server select(List<Server> servers) {
        if (servers == null || servers.isEmpty() || source == null) return null;
        int hash = source.hashCode();
        int index = (hash & 0x7FFFFFFF) % servers.size(); // 避免負數(shù)
        return servers.get(index);
    }
}

優(yōu)點:會話保持(Session Stickiness)

缺點:節(jié)點增減會導致大量映射失效(可改用一致性哈希)

7. 一致性哈希(Consistent Hashing)

解決普通哈希在節(jié)點動態(tài)變化時緩存/會話大量失效的問題。

public class ConsistentHashingLoadBalancer implements LoadBalancer {
    private final SortedMap<Integer, Server> circle = new TreeMap<>();
    private final int virtualNodes; // 虛擬節(jié)點數(shù)

    public ConsistentHashingLoadBalancer(int virtualNodes) {
        this.virtualNodes = virtualNodes;
    }

    public void addServer(Server server) {
        for (int i = 0; i < virtualNodes; i++) {
            int hash = hash(server.getHost() + ":" + server.getPort() + "#" + i);
            circle.put(hash, server);
        }
    }

    public void removeServer(Server server) {
        for (int i = 0; i < virtualNodes; i++) {
            int hash = hash(server.getHost() + ":" + server.getPort() + "#" + i);
            circle.remove(hash);
        }
    }

    private int hash(String key) {
        return key.hashCode(); // 簡化,生產(chǎn)建議用 MD5 或 MurmurHash
    }

    @Override
    public Server select(List<Server> servers) {
        if (circle.isEmpty()) {
            // 動態(tài)構(gòu)建環(huán)(實際應提前構(gòu)建)
            servers.forEach(this::addServer);
        }
        if (circle.isEmpty()) return null;

        // 假設 source 為請求 ID 或 IP
        String requestKey = "request_" + System.nanoTime(); // 實際應由調(diào)用方提供
        int hash = hash(requestKey);

        if (!circle.containsKey(hash)) {
            SortedMap<Integer, Server> tailMap = circle.tailMap(hash);
            hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
        }
        return circle.get(hash);
    }
}

節(jié)點增減只影響局部數(shù)據(jù)

廣泛用于緩存、分布式存儲系統(tǒng)

總結(jié)對比

算法是否考慮權(quán)重是否有狀態(tài)適用場景
隨機??簡單快速分發(fā)
輪詢??(位置)請求均勻、節(jié)點同質(zhì)
加權(quán)輪詢??節(jié)點性能不同
平滑加權(quán)輪詢??更公平的加權(quán)分發(fā)
最少連接?(但看負載)?長連接、異構(gòu)任務
源地址哈希??會話保持
一致性哈希?(可擴展支持)?(哈希環(huán))緩存、分布式存儲

結(jié)語

通過手寫這七種負載均衡算法,我們不僅掌握了其實現(xiàn)細節(jié),也理解了它們各自的優(yōu)劣和適用邊界。在真實項目中,可根據(jù)業(yè)務需求靈活選擇或組合使用(例如:先一致性哈希定位節(jié)點組,再在組內(nèi)輪詢)。

提示:生產(chǎn)環(huán)境建議使用成熟組件(如 Ribbon、Spring Cloud LoadBalancer、Nginx、LVS),但理解底層原理永遠是工程師的核心競爭力。

以上就是從零帶你手寫Java七種負載均衡算法實現(xiàn)方案的詳細內(nèi)容,更多關(guān)于Java負載均衡算法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring的連接數(shù)據(jù)庫以及JDBC模板(實例講解)

    Spring的連接數(shù)據(jù)庫以及JDBC模板(實例講解)

    下面小編就為大家?guī)硪黄猄pring的連接數(shù)據(jù)庫以及JDBC模板(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Java爬蟲爬取漫畫示例

    Java爬蟲爬取漫畫示例

    這篇文章主要介紹了Java爬蟲爬取漫畫示例,大部分的爬蟲入門教學都是爬取圖片的,本文就來測試一下爬取網(wǎng)站的漫畫,需要的朋友可以參考下
    2023-04-04
  • IntelliJ IDEA中代碼一鍵生成方法

    IntelliJ IDEA中代碼一鍵生成方法

    EasyCode 是基于 IntelliJ IDEA 開發(fā)的代碼生成插件,支持自定義任意模板(Java,html,js,xml),這篇文章主要介紹了IntelliJ IDEA中代碼一鍵生成方法,需要的朋友可以參考下
    2020-02-02
  • Java中覆蓋finalize()方法實例代碼

    Java中覆蓋finalize()方法實例代碼

    這篇文章主要介紹了Java中覆蓋finalize()方法實例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • 關(guān)于JFormDesigner的安裝及破姐超詳細教程

    關(guān)于JFormDesigner的安裝及破姐超詳細教程

    JFormDesigner是一種先進的圖形用戶界面Swing?的設計工具(非開源),具有一個獨立的開發(fā)工具產(chǎn)品和基于不同開發(fā)工具如Eclipse、NetBeans等的開發(fā)插件,本文給大家介紹JFormDesigner安裝破解教程,感興趣的朋友一起看看吧
    2023-12-12
  • Spring @ExceptionHandler注解統(tǒng)一異常處理和獲取方法名

    Spring @ExceptionHandler注解統(tǒng)一異常處理和獲取方法名

    這篇文章主要介紹了Spring注解之@ExceptionHandler 統(tǒng)一異常處理和獲取方法名,在實際項目中,合理使用@ExceptionHandler能夠提高代碼的可維護性和用戶體驗,通過本文的解析和實踐,讀者可以更好地理解和掌握@ExceptionHandler的用法和原理
    2023-09-09
  • spring整合redis以及使用RedisTemplate的方法

    spring整合redis以及使用RedisTemplate的方法

    本篇文章主要介紹了spring整合redis以及使用RedisTemplate的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Java中三種零拷貝的實現(xiàn)示例以及對比詳解

    Java中三種零拷貝的實現(xiàn)示例以及對比詳解

    這篇文章主要介紹了Java中三種零拷貝的實現(xiàn)示例以及對比詳解,本文主要是介紹幾種零拷貝的實現(xiàn)示例,以及與最傳統(tǒng)的做一個對比,看看在效率上到底有多大的提升,需要的朋友可以參考下
    2023-12-12
  • Struts2 自定義下拉框Tag標簽

    Struts2 自定義下拉框Tag標簽

    這篇文章主要介紹了Struts2 自定義下拉框Tag標簽的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • Java Web中常用的分頁組件(Java端實現(xiàn))

    Java Web中常用的分頁組件(Java端實現(xiàn))

    本文通過使用場景分析給大家介紹了Java Web中常用的分頁組件(Java端實現(xiàn)),非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-05-05

最新評論

永定县| 阿荣旗| 滦平县| 红原县| 涪陵区| 汉寿县| 河曲县| 巴楚县| 乡城县| 若尔盖县| 阿尔山市| 尼勒克县| 西宁市| 宁河县| 扶沟县| 桦川县| 老河口市| 清水县| 青阳县| SHOW| 长阳| 崇信县| 嘉峪关市| 分宜县| 繁峙县| 玉环县| 阜城县| 舞钢市| 石景山区| 灌南县| 六盘水市| 安吉县| 兴义市| 板桥市| 英超| 漳州市| 扶风县| 茂名市| 肥东县| 界首市| 瑞安市|