目录结构:
按目录结构顺序上传:
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;
}
}
结果: