本地模拟一台客户端三台服务器的负载均衡算法过程

目录结构:

按目录结构顺序上传:

ServicePort:定义端口值、权重值

package com.load.balancing.config;

import java.util.*;

public class ServicePort {
    //不带权重
    public static final List<String> LIST = Arrays.asList(
            "8081",
            "8082",
            "8083"
    );
    //带权重
    public static final HashMap<String,Integer> WEIGHT_MAP = new LinkedHashMap<>();
    static {
        WEIGHT_MAP.put("8081",20);
        WEIGHT_MAP.put("8082",30);
        WEIGHT_MAP.put("8083",50);
    }
}

WeightInfo:封装端口、权重值、当前权重值,便于后续操作

package com.load.balancing.config;

public class WeightInfo {
    public  String port;
    public Integer curWeight;
    public Integer weight;
    public WeightInfo(String port, Integer curWeight, Integer weight){
        this.port = port;
        this.curWeight = curWeight;
        this.weight = weight;
    }
}

ClientLoad:客户端访问

package com.load.balancing.Controller;

import com.load.balancing.service.CallLoadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ClientLoad {
    @Autowired
    CallLoadService callLoadService;
    @GetMapping(value = "call/{loadType}/{times}")
    public  String CallService(@PathVariable String loadType, @PathVariable int times){
        return callLoadService.loadService(loadType,times);
    }
}

ServerLoad:服务器端访问

package com.load.balancing.Controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.atomic.AtomicInteger;
@RestController
public class ServerLoad {
    AtomicInteger callTimes = new AtomicInteger();

    @GetMapping(value = "/hello")
    public int hello(){
        callTimes.incrementAndGet();
        return  callTimes.get();
    }

    @GetMapping(value = "/times")
    public int countTimes(){
        return callTimes.get();
    }
}

CallLoadService:负载的策略,远程访问服务器端资源

package com.load.balancing.service;


import com.load.balancing.config.ServicePort;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class CallLoadService {
     final String url = "http://localhost:";
     final String method = "/hello";

     //负载策略
     public String loadService(String loadType, int times){
        ConcurrentHashMap serverName = new ConcurrentHashMap();
        serverName.put("8081","serverA");
        serverName.put("8082","serverB");
        serverName.put("8083","serverC");
         String port;
         StringBuffer sb = new StringBuffer();
         for (int i = 0; i < times; i++){
             switch (loadType){
                 case "random":
                     port = LoadService.RandomBalance();
                     break;
                 case "weight":
                     port = LoadService.WeightBalance();
                     break;
                 default:
                     port = LoadService.RandomBalance();;
             }
            sb.append("</br>" + serverName.get(port) + "服务器被调用的端口是:" + port + ",被访问的次数是:" + callService(url,port, method) + "</br>");
         }

         for (String ipPort : ServicePort.LIST){
             sb.append("<br>" + "服务名为"+ serverName.get(ipPort) +" ,端口:"+ ipPort + ",最终统计已被调用 "+callService(url,ipPort, "/times")+"次 </br>");
         }
         return sb.toString();
    }

    //远程调用服务器资源
    public String callService(String url , String port ,String methodName){
        HttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet httpRequest = new HttpGet(url + port + methodName);
        httpRequest.setHeader("Content-Type","application/json");
        httpRequest.setHeader("Accept","application/json");
        HttpResponse httpResponse;
        try {
            httpResponse = httpClient.execute(httpRequest);
            return EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
            return "请求转换失败" + e.getMessage();
        }
        finally {
            try {
                ((CloseableHttpClient)httpClient).close();
            } catch (IOException e) {
                e.printStackTrace();
                return "请求关闭失败" + e.getMessage();
            }
        }
    }
}

LoadService:负载均衡算法

package com.load.balancing.service;

import com.load.balancing.config.ServicePort;
import com.load.balancing.config.WeightInfo;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Service
public class LoadService {
    private static Map<String, WeightInfo> weightPathMap = new HashMap();

    //随机算法
    public static String RandomBalance(){
        Random random = new Random();
        int port = random.nextInt(3);
        return ServicePort.LIST.get(port);
    }

    //权重算法
    public static String WeightBalance(){

        //拿到总权重
        int totalWeight = 0;
        for (Integer weight : ServicePort.WEIGHT_MAP.values()){
            totalWeight += weight;
        }
        //初始化动态权重值
        if (weightPathMap.isEmpty()){
            ServicePort.WEIGHT_MAP.forEach((port,weight) -> weightPathMap.put(port,new WeightInfo(port,weight,0)));
        }
        WeightInfo maxWeightPath = null;
        for (WeightInfo weightPath : weightPathMap.values()){
            if (maxWeightPath == null || weightPath.curWeight > maxWeightPath.curWeight){
                maxWeightPath = weightPath;
            }
        }
        //减去总权重
        maxWeightPath.curWeight -= totalWeight;
        //获取对应的端口
        return maxWeightPath.port;
    }
}

结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半生程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值