暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

简单易懂:使用 Java 实现 6 种常见负载均衡算法

原创 April 2023-06-14
195

璐熻浇鍧囪 鏄寚灏嗘潵鑷鎴风鐨勮姹傚垎鎽婂埌澶氫釜鏈嶅姟鍣ㄤ笂杩涜澶勭悊锛屼粠鑰屾湁鏁堝湴鎻愰珮绯荤粺鎬ц兘銆佸彲鐢ㄦ�у拰鍙墿灞曟�с�傚父瑙佺殑璐熻浇鍧囪 绠楁硶鍖呮嫭杞娉曘�佸姞鏉冭疆璇㈡硶銆侀殢鏈烘硶銆佸姞鏉冮殢鏈烘硶銆佹簮鍦板潃鍝堝笇娉曞拰鏈�灏忚繛鎺ユ暟娉曠瓑銆�

image.png

鍦ㄥ疄闄呭簲鐢ㄤ腑鏈夊緢澶氬伐鍏峰拰妗嗘灦浣跨敤浜嗚繖浜涚畻娉曟潵瑙e喅鏈嶅姟鍣ㄨ礋杞藉潎琛$殑闂銆備笅闈㈡垜鏁寸悊鍑轰簡涓�浜涘父瑙佺殑宸ュ叿鍜屾鏋讹細

  1. Nginx锛歂ginx 鏄竴娆鹃珮鎬ц兘鐨� Web 鏈嶅姟鍣紝鍚屾椂涔熸槸涓�娆惧弽鍚戜唬鐞嗘湇鍔″櫒銆侼ginx 鐨勮礋杞藉潎琛℃ā鍧楁敮鎸佸绉嶇畻娉曪紝鍖呮嫭杞娉曘�佸姞鏉冭疆璇㈡硶銆両P_HASH 绛夈��

  2. Apache锛欰pache 鏄竴娆炬祦琛岀殑 Web 鏈嶅姟鍣ㄣ�侫pache 涔熸彁渚涗簡璐熻浇鍧囪 妯″潡锛屾敮鎸佸绉嶇畻娉曪紝鍖呮嫭杞娉曘�佸姞鏉冭疆璇㈡硶銆佹渶灏忚繛鎺ユ暟娉曠瓑銆�

  3. HAProxy锛欻AProxy 鏄竴娆鹃珮鎬ц兘鐨� TCP/HTTP 璐熻浇鍧囪 鍣紝鏀寔澶氱璐熻浇鍧囪 绠楁硶锛屽寘鎷疆璇㈡硶銆佸姞鏉冭疆璇㈡硶銆両P_HASH銆佹渶灏戣繛鎺ユ暟娉曘�佹渶鐭搷搴旀椂闂存硶绛夈��

  4. Spring Cloud Ribbon锛歊ibbon 鏄竴娆惧熀浜� HTTP 鍜� TCP 瀹㈡埛绔殑璐熻浇鍧囪 鍣紝鏄� Spring Cloud 鐢熸�佺郴缁熶腑鐨勪竴鍛樸�俁ibbon 鏀寔澶氱璐熻浇鍧囪 绠楁硶锛屽寘鎷疆璇㈡硶銆佸姞鏉冭疆璇㈡硶銆侀殢鏈烘硶绛夈��

  5. ZooKeeper锛歓ooKeeper 鏄竴娆惧垎甯冨紡鍗忚皟鏈嶅姟锛屽湪鍒嗗竷寮忕郴缁熶腑骞挎硾搴旂敤銆俍ooKeeper 鐨勫鎴风搴� Curator 鎻愪緵浜嗕竴绉嶅熀浜� ZooKeeper 鐨勮礋杞藉潎琛$畻娉曪紝绉颁负 Dynamic Server List Load Balancing銆�

杩欎簺宸ュ叿鍜屾鏋堕兘搴旂敤浜嗚礋杞藉潎琛$畻娉曟潵瀹炵幇鏈嶅姟鍣ㄧ殑璐熻浇鍧囪 锛屽畠浠殑瀹炵幇鏂瑰紡涔熷悇涓嶇浉鍚岋紝浣嗘槸灏界濡傛锛屾垜浠彲浠ヤ粠涓涔犲埌寰堝鏈変环鍊肩殑缁忛獙鍜屾�濊矾銆�

鍒掗噸鐐� Java 鏋舵瀯甯堝繀澶囨妧鑳�-鎴戜滑瑕佹繁鍏ュ涔犲悇绫昏礋杞藉潎琛$畻娉曞疄鐜版柟寮�

Java璐熻浇鍧囪 绠楁硶涔熸槸鍒嗗竷寮忕郴缁熶腑鐨勯噸瑕佺粍鎴愰儴鍒嗭紝鐢ㄤ簬灏嗘潵鑷鎴风鐨勮姹傚垎閰嶅埌涓嶅悓鐨勫悗绔湇鍔″櫒涓婏紝浠ヨ揪鍒版彁楂樼郴缁熷悶鍚愰噺銆佸噺杞绘湇鍔″櫒璐熸媴銆佹彁楂樼郴缁熷彲鐢ㄦ�х瓑鐩殑銆傛湰鏂囧皢浠嬬粛甯歌鐨凧ava璐熻浇鍧囪 绠楁硶锛岃疆璇㈡硶銆佸姞鏉冮殢鏈烘硶鈥︹�︿竴娆℃�ц浣犱簡瑙� 6 绉嶅父瑙�璐熻浇鍧囪 绠楁硶銆�

涓�銆佽疆璇㈡硶锛圧ound Robin锛�

杞娉曟槸鏈�绠�鍗曘�佹渶甯歌鐨勮礋杞藉潎琛$畻娉曚箣涓�锛屽叾瀹炵幇鎬濊矾涔熼潪甯哥畝鍗曪細鎸夌収浜嬪厛瑙勫畾鐨勯『搴忎緷娆″皢璇锋眰杞彂鑷冲悗绔湇鍔″櫒銆備緥濡傦紝鑻ユ湁3鍙版湇鍔″櫒锛屽垯绗�1涓姹備細琚垎閰嶅埌绗�1鍙版湇鍔″櫒涓婏紝绗�2涓姹備細琚垎閰嶅埌绗�2鍙版湇鍔″櫒涓婏紝绗�3涓姹備細琚垎閰嶅埌绗�3鍙版湇鍔″櫒涓婏紝绗�4涓姹傚張浼氳鍒嗛厤鍒扮1鍙版湇鍔″櫒涓婏紝浠ユ绫绘帹銆�

杩欑绠楁硶鐨勪紭鐐规槸瀹炵幇绠�鍗曘�佸彲闈犳�ч珮锛屼絾鏄畠骞舵病鏈夎�冭檻鏈嶅姟鍣ㄧ殑瀹為檯璐熻浇鎯呭喌锛屽鑷存煇浜涙湇鍔″櫒鍙兘浼氭壙鍙楄繃澶氱殑璐熻浇锛岃�屽叾浠栨湇鍔″櫒鍒欏浜庣┖闂茬姸鎬併��

杞娉曪紙Round Robin锛夊啓涓畝鍗曠殑瀹炵幇浠g爜璁╀綘鎰熻涓�涓嬶細

//瀹氫箟涓�涓叏灞�璁℃暟鍣紝姣忔璋冪敤绱姞
private static AtomicInteger atomicInteger = new AtomicInteger(0);
//瀹氫箟鏈嶅姟鍣ㄥ垪琛�
private static List<String> serverList = new ArrayList<>();

public static String roundRobin() {
    //鑾峰彇鏈嶅姟鍣ㄦ暟閲�
    int serverCount = serverList.size();
    //鑾峰彇褰撳墠璇锋眰搴旇杞彂鍒板摢鍙版湇鍔″櫒
    int currentServerIndex = atomicInteger.incrementAndGet() % serverCount;
    //杩斿洖瀵瑰簲鐨勬湇鍔″櫒鍦板潃
    return serverList.get(currentServerIndex);
}

浜屻�佸姞鏉冭疆璇㈡硶锛圵eight Round Robin锛�

鍔犳潈杞娉曟槸鍦ㄨ疆璇㈡硶鐨勫熀纭�涓婅繘琛屾敼杩涳紝鍏舵�濊矾鏄湪鏈嶅姟鍣ㄧ殑閫夋嫨涓紝鏍规嵁鏈嶅姟鍣ㄧ殑澶勭悊鑳藉姏鎴栬礋杞芥儏鍐靛垎閰嶄笉鍚岀殑鏉冮噸锛屼互浣垮鐞嗚兘鍔涜緝寮烘垨璐熻浇杈冭交鐨勬湇鍔″櫒鑾峰緱鏇村鐨勮姹傘�備緥濡傦紝鑻ュ瓨鍦�2鍙版湇鍔″櫒锛屽叾涓1鍙版湇鍔″櫒璐熻浇姣旇緝閲嶏紝鍒欏簲褰撳皢鏇村鐨勮姹傚垎閰嶇粰绗�2鍙版湇鍔″櫒銆�

涓句釜渚嬪瓙锛屽鏋滄湇鍔″櫒A鐨勬潈閲嶆槸2锛屾湇鍔″櫒B鐨勬潈閲嶆槸1锛岄偅涔堝湪涓や釜璇锋眰涓紝鏈変竴涓姹備細琚彂閫佸埌鏈嶅姟鍣ˋ锛屽彟涓�涓姹傚皢琚彂閫佸埌鏈嶅姟鍣˙銆�

杩欑绠楁硶鐨勪紭鐐规槸鍙互鏍规嵁鏈嶅姟鍣ㄧ殑瀹為檯璐熻浇鎯呭喌鏉ュ垎閰嶈姹傦紝浣嗘槸杩樻槸瀛樺湪鏈嶅姟鍣ㄨ礋杞戒笉鍧囪 鐨勯棶棰橈紝鍥犱负瀹冨彧鏄牴鎹潈鍊艰繘琛屽垎閰嶏紝骞舵病鏈夎�冭檻鏈嶅姟鍣ㄧ殑瀹為檯璐熻浇鎯呭喌銆�

鍔犳潈杞娉曟寜鑷繁鐨勬�濊矾鍐欎竴涓嬪涓嬬ず渚嬶細

//瀹氫箟涓�涓叏灞�璁℃暟鍣紝姣忔璋冪敤绱姞
private static AtomicInteger atomicInteger = new AtomicInteger(0);
//瀹氫箟鏈嶅姟鍣ㄥ垪琛ㄥ強鏈嶅姟鍣ㄦ潈閲嶅��
private static Map<String, Integer> serverMap = new ConcurrentHashMap<>();
//璁板綍鏈嶅姟鍣ㄦ潈閲嶆�诲拰
private static int totalWeight = 0;

public static String weightRoundRobin() {
    //鑾峰彇鏈嶅姟鍣ㄦ暟閲�
    int serverCount = serverMap.size();
    //濡傛灉娌℃湁鍙敤鐨勬湇鍔″櫒杩斿洖null
    if (serverCount == 0) {
        return null;
    }
    //鍦ㄦ澶勪负閬垮厤澶氱嚎绋嬪苟鍙戞搷浣滈�犳垚閿欒锛屽湪鏂规硶鍐呴儴杩涜閿佹搷浣�
    synchronized (serverMap) {
        //璁$畻鏈嶅姟鍣ㄦ潈閲嶆�诲拰
        for (Map.Entry<String, Integer> entry : serverMap.entrySet()) {
            totalWeight += entry.getValue();
        }
        //鑾峰彇褰撳墠璇锋眰搴旇杞彂鍒板摢鍙版湇鍔″櫒
        int currentServerIndex = atomicInteger.incrementAndGet() % totalWeight;
        //閬嶅巻鏈嶅姟鍣ㄥ垪琛紝鏍规嵁鏈嶅姟鍣ㄦ潈閲嶅�奸�夋嫨瀵瑰簲鍦板潃
        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;
        }
    }
}

涓夈�侀殢鏈烘硶锛圧andom锛�

闅忔満娉曟槸鎸囧皢璇锋眰闅忔満鍒嗛厤鑷冲悗绔湇鍔″櫒鐨勮礋杞藉潎琛$畻娉曘�傝绠楁硶瀹炵幇绠�鍗曪紝浣嗗垎閰嶆晥鏋滀笉鍙帶锛岄毦浠ヤ繚璇佸悗绔湇鍔″櫒鐨勮礋杞藉潎琛°�傚洜姝わ紝闅忔満娉曢�氬父琚敤浣滄祴璇曟垨鍘嬪姏娴嬭瘯绛変复鏃跺満鏅笅鐨勮礋杞藉潎琛$畻娉曘��

闅忔満娉曞疄鐜颁唬鐮佸涓嬶細

// 1銆佹�濊矾鍙傝�冿細-----------------------------------------------
//瀹氫箟鏈嶅姟鍣ㄥ垪琛�
private static List<String> serverList = new ArrayList<>();

public static String random() {
    //鑾峰彇鏈嶅姟鍣ㄦ暟閲�
    int serverCount = serverList.size();
    //濡傛灉娌℃湁鍙敤鐨勬湇鍔″櫒杩斿洖null
    if (serverCount == 0) {
        return null;
    }
    //鐢熸垚涓�涓殢鏈烘暟
    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);
    }
}

鍥涖�佸姞鏉冮殢鏈烘硶锛圵eight Random锛�

鍔犳潈闅忔満娉曟槸鍦ㄩ殢鏈烘硶鐨勫熀纭�涓婅繘琛屾敼杩涳紝鍏舵�濊矾鏄湪鏈嶅姟鍣ㄧ殑閫夋嫨涓紝鏍规嵁鏈嶅姟鍣ㄧ殑澶勭悊鑳藉姏鎴栬礋杞芥儏鍐靛垎閰嶄笉鍚岀殑鏉冮噸锛屼互浣垮鐞嗚兘鍔涜緝寮烘垨璐熻浇杈冭交鐨勬湇鍔″櫒鑾峰緱鏇村鐨勮姹傘��

鍔犳潈闅忔満娉曞疄鐜颁唬鐮佸涓嬶細

// 1銆佹�濊矾鍙傝�冿細-----------------------------------------------------------
//瀹氫箟鏈嶅姟鍣ㄥ垪琛ㄥ強鏈嶅姟鍣ㄦ潈閲嶅��
private static Map<String, Integer> serverMap = new ConcurrentHashMap<>();
//璁板綍鏈嶅姟鍣ㄦ潈閲嶆�诲拰
private static int totalWeight = 0;

public static String weightRandom() {
    //鑾峰彇鏈嶅姟鍣ㄦ暟閲�
    int serverCount = serverMap.size();
    //濡傛灉娌℃湁鍙敤鐨勬湇鍔″櫒杩斿洖null
    if (serverCount == 0) {
        return null;
    }
    //鍦ㄦ澶勪负閬垮厤澶氱嚎绋嬪苟鍙戞搷浣滈�犳垚閿欒锛屽湪鏂规硶鍐呴儴杩涜閿佹搷浣�
    synchronized (serverMap) {
        //璁$畻鏈嶅姟鍣ㄦ潈閲嶆�诲拰
        for (Map.Entry<String, Integer> entry : serverMap.entrySet()) {
            totalWeight += entry.getValue();
        }
        //鐢熸垚涓�涓殢鏈烘暟
        int randomWeight = new Random().nextInt(totalWeight);
        //閬嶅巻鏈嶅姟鍣ㄥ垪琛紝鏍规嵁鏈嶅姟鍣ㄦ潈閲嶅�奸�夋嫨瀵瑰簲鍦板潃
        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鍦板潃閫氳繃鍝堝笇鍑芥暟璁$畻鍑轰竴涓�硷紝鐒跺悗鏍规嵁璇ュ�间笌鍙敤鏈嶅姟鍣ㄦ�绘暟鍙栨ā鐨勭粨鏋滄潵纭畾璇ヨ姹傚簲褰撹浆鍙戝埌鍝彴鏈嶅姟鍣ㄤ笂銆�

鎹㈣█涔嬶紝婧愬湴鍧�鍝堝笇绠楁硶灏辨槸浣跨敤瀹㈡埛绔� IP 鍦板潃浣滀负鍝堝笇閿�傝礋杞藉潎琛″櫒灏嗗搱甯屽�兼槧灏勫埌鍙敤鏈嶅姟鍣ㄤ腑鐨勪竴涓紝鐒跺悗灏嗚姹傚彂閫佸埌杩欎釜鏈嶅姟鍣ㄥ鐞嗐�傚鏋滃鎴风 IP 鍦板潃鍙戠敓鏀瑰彉锛堟瘮濡傞噸鍚悗閲嶆柊鍒嗛厤 IP 鍦板潃锛夛紝閭d箞灏嗕細琚垎閰嶅埌鍏朵粬鏈嶅姟鍣ㄤ笂銆�

杩欑绠楁硶鐨勪紭鐐规槸鍙互閬垮厤鏌愪簺瀹㈡埛绔閲嶅畾鍚戝埌涓嶅悓鐨勬湇鍔″櫒锛屽浜庡悓涓�IP鍦板潃鐨勮姹傦紝鎬绘槸浼氳鍒嗛厤鍒板悓涓�鍙版湇鍔″櫒涓婏紝鍥犳鍙互鍦ㄤ竴瀹氱▼搴︿笂鎻愰珮缂撳瓨鍛戒腑鐜囩瓑鎬ц兘鎸囨爣锛屼絾鏄畠涔熸湁涓�浜涚己鐐广�備緥濡傦紝濡傛灉鏈夊緢澶氳姹傛潵鑷浉鍚岀殑 IP 鍦板潃锛岄偅涔堝彲鑳戒細瀵艰嚧鏌愪釜鏈嶅姟鍣ㄨ礋杞借繃楂樸�傚彟澶栵紝鐢变簬鏈嶅姟鍣ㄦ暟閲忕殑鍙樺寲锛屽搱甯屽�兼槧灏勪篃浼氬彂鐢熷彉鍖栵紝杩欏彲鑳戒細瀵艰嚧缂撳瓨鏃犳晥锛屽苟涓旈渶瑕侀噸鏂板垎閰嶆墍鏈夎姹傘��

婧愬湴鍧�鍝堝笇娉曞疄鐜颁唬鐮佺ず渚嬪涓嬶細

// 1銆佹�濊矾鍙傝�冿細-----------------------------------------------------------
//瀹氫箟鏈嶅姟鍣ㄥ垪琛�
private static List<String> serverList = new ArrayList<>();

public static String hash(String clientIP) {
    //鑾峰彇鏈嶅姟鍣ㄦ暟閲�
    int serverCount = serverList.size();
    //濡傛灉娌℃湁鍙敤鐨勬湇鍔″櫒杩斿洖null
    if (serverCount == 0) {
        return null;
    }
    //灏嗗鎴风IP鍦板潃杩涜鍝堝笇璁$畻
    int hashCode = clientIP.hashCode();
    //鏍规嵁鍝堝笇鍊艰绠楅渶瑕佽浆鍙戝埌鍝彴鏈嶅姟鍣ㄤ笂
    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() {
        // 鑾峰彇瀹㈡埛绔疘P鍦板潃鐨勪唬鐮佺渷鐣�
        return "1.1.1.1";
    }
}

鍏�佹渶灏忚繛鎺ユ暟娉曪紙Least Connections锛�

鏈�灏忚繛鎺ユ暟娉曟槸涓�绉嶅姩鎬佽皟鏁寸殑璐熻浇鍧囪 绠楁硶锛屽叾鎬濊矾鏄敖鍙兘鍦板皢璇锋眰鍒嗛厤缁欏綋鍓嶇┖闂茶繛鎺ユ暟鏈�灏戠殑鍚庣鏈嶅姟鍣紝浠ヨ揪鍒拌礋杞藉潎琛$殑鏁堟灉銆傚湪瀹炵幇杩囩▼涓紝閫氬父闇�瑕佸畾鏈熸娴嬪悇涓湇鍔″櫒鐨勮繛鎺ユ暟骞惰繘琛屽姩鎬佽皟鏁淬��

鏈�灏忚繛鎺ユ暟绠楁硶鏄牴鎹綋鍓嶈繛鎺ユ暟鏉ラ�夋嫨涓�涓彲鐢ㄦ湇鍔″櫒銆傝礋杞藉潎琛″櫒浼氭煡璇㈠彲鐢ㄦ湇鍔″櫒鐨勮繛鎺ユ暟锛岀劧鍚庨�夋嫨涓�涓繛鎺ユ暟鏈�灏忕殑鏈嶅姟鍣ㄣ�傝繖绉嶇畻娉曚繚璇佷簡鏈嶅姟鍣ㄤ笉浼氳杩囧害璐熻浇锛屽苟涓旇繕鍏佽璐熻浇鍧囪 鍣ㄦ牴鎹疄闄呮儏鍐靛姩鎬佸垎閰嶈姹傘��

闇�瑕佹敞鎰忕殑鏄紝濡傛灉鏈嶅姟鍣ㄦ寕鎺変簡鎴栬�呯綉缁滈摼璺腑鏂簡锛岄偅涔堣礋杞藉潎琛″櫒灏遍渶瑕侀噸鏂拌绠楁湇鍔″櫒鐨勮繛鎺ユ暟锛岃繖灏嗗欢闀垮搷搴旀椂闂村苟涓斿奖鍝嶆�ц兘銆�

鏈�灏忚繛鎺ユ暟娉曞疄鐜颁唬鐮佺ず渚嬪涓嬶細

// 1銆佹�濊矾鍙傝�冿細-----------------------------------------------------------
//瀹氫箟鏈嶅姟鍣ㄥ垪琛�
private static List<String> serverList = new ArrayList<>();

//璁板綍姣忎釜鏈嶅姟鍣ㄧ殑杩炴帴鏁�
private static Map<String, Integer> connectionsMap = new ConcurrentHashMap<>();

public static String leastConnections() {
    //鑾峰彇鏈嶅姟鍣ㄦ暟閲�
    int serverCount = serverList.size();
    //濡傛灉娌℃湁鍙敤鐨勬湇鍔″櫒杩斿洖null
    if (serverCount == 0) {
        return null;
    }
    //榛樿閫夋嫨绗竴涓湇鍔″櫒
    String selectedServerAddress = serverList.get(0);
    //鑾峰彇绗竴涓湇鍔″櫒鐨勮繛鎺ユ暟
    int minConnections = connectionsMap.getOrDefault(selectedServerAddress, 0);
    //閬嶅巻鏈嶅姟鍣ㄥ垪琛紝瀵绘壘杩炴帴鏁版渶灏戠殑鏈嶅姟鍣�
    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;
        }
    }
    //杩斿洖杩炴帴鏁版渶灏戠殑鏈嶅姟鍣ㄥ湴鍧�
    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);
    }
}

浠ヤ笂渚挎槸甯歌鐨凧ava璐熻浇鍧囪 绠楁硶锛岃繖浜涚畻娉曢兘鏈夊叾鑷韩鐨勪紭缂虹偣鍜岄�傜敤鍦烘櫙銆�

涓冦�佸皬缁撲竴涓�

Java 鏋舵瀯甯堥潰涓寸殑鎸戞垬瓒婃潵瓒婂ぇ锛屾垜浠渶瑕佸湪涓嶆柇鍙戝睍鐨勬妧鏈腑淇濇寔鏁忛攼鐨勮Е瑙夛紝骞舵帉鎻¤秺鏉ヨ秺骞挎硾鐨勭煡璇嗐�傝�屽湪褰撳墠浜掕仈缃戞灦鏋勪腑锛岃礋杞藉潎琛$畻娉曟槸涓�涓嚦鍏抽噸瑕佺殑棰嗗煙銆傚畠鏄疄鐜版湇鍔$殑楂樺彲鐢ㄦ�у拰鍙几缂╂�х殑閲嶈鎵嬫銆傚洜姝わ紝Java 鏋舵瀯甯堝繀椤绘繁鍏ュ涔犲悇绫昏礋杞藉潎琛$畻娉曠殑瀹炵幇鏂瑰紡锛屽苟涓旂悊瑙e畠浠殑浼樺姡涔嬪锛屼互渚夸负鍏徃璁捐鍑烘洿濂界殑缃戠粶鏋舵瀯銆�

濡傛灉浣犳兂鎴愪负涓�鍚� Java 鏋舵瀯甯堟垨鑰呯綉缁滃伐绋嬪笀锛岄偅涔堝笇鏈涗綘澶氬浜嗚В搴曞眰鐭ヨ瘑瀵逛綘灏嗗ぇ鏈夌泭澶勩�傝鎴戜滑涓�璧峰姫鍔涘惂锛�

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论