import com.google.common.collect.Lists;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 轮询算法
* 轮询算法按顺序把每个新的连接请求分配给下一个服务器,最终把所有请求平分给所有的服务器。
* 优点:绝对公平
* 缺点:无法根据服务器性能去分配,无法合理利用服务器资源。
* @author:
* @date: 2022-11-10 17:53
*/
public class Round<T> {
private AtomicInteger index = new AtomicInteger(0);
public <T> T roundRobin(List<T> data) {
T t ;
if (index.get() >= data.size()) {
index = new AtomicInteger(0);
}
t = data.get(index.get());
//轮询+1
index.getAndIncrement();
return t;
}
public static void main(String[] args) {
List<String> ips = Lists.newArrayList("192.168.1.1", "192.168.1.2", "192.168.1.3");
Round<String> testRoundRobin =new Round<String>();
for (int i=0;i< 10 ;i++){
String s = testRoundRobin.roundRobin(ips);
System.out.println(s);
}
}
}
import com.collmall.shortlink.entity.DbConfig;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 加权轮询法
* 该算法中,每个机器接受的连接数量是按权重比例分配的。这是对普通轮询算法的改进,
* 比如你可以设定:第三台机器的处理能力是第一台机器的两倍,那么负载均衡器会把两倍的连接数量分配给第3台机器,轮询可以将请求顺序按照权重分配到后端。
* @author
* @date 2022年11月11日14:46:25
*/
public class Weight<T> {
private AtomicInteger index = new AtomicInteger(0);
public List<T> getDataByWeight(List<T> data) throws NoSuchFieldException, IllegalAccessException {
List<T> ips = new CopyOnWriteArrayList<T>();
if (CollectionUtils.isEmpty(data)) {
return data;
}
for (T t : data) {
Field nameField = t.getClass().getDeclaredField("name");
// setAccessible 实体中的属性是用private定义的,需要设置setAccessible 为true,才可以访问到对象
nameField.setAccessible(true);
// 获取属性值
String name =(String) nameField.get(t);
Field weightField = t.getClass().getDeclaredField("weight");
// setAccessible 实体中的属性是用private定义的,需要设置setAccessible 为true,才可以访问到对象
weightField.setAccessible(true);
// 获取属性值
Integer weight = (Integer) weightField.get(t);
for (int ipCount =0; ipCount < weight; ipCount++) {
ips.add(t);
}
}
return ips;
}
public T weightRobin(List<T> data) throws NoSuchFieldException, IllegalAccessException {
List<T> list = this.getDataByWeight(data);
if (index.get() >= list.size()){
index = new AtomicInteger(0);
}
T t = list.get(index.get());
index.getAndIncrement();
return t;
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Weight testWeightRobin=new Weight();
List<DbConfig> dbConfigList= new ArrayList<>();
dbConfigList.add(new DbConfig("192.168.1.1", 1));
dbConfigList.add(new DbConfig("192.168.1.2", 2));
dbConfigList.add(new DbConfig("192.168.1.3", 4));
for (int i =0;i< 10 ;i++){
DbConfig server = (DbConfig)testWeightRobin.weightRobin(dbConfigList);
System.out.println(server);
}
}
}
import com.collmall.shortlink.entity.DbConfig;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadLocalRandom;
/**
* 加权随机法
* 获取带有权重的随机数字,随机这种东西,不能看绝对,只能看相对,
* 我们不用index 控制下标进行轮询,只用random 进行随机取ip,即实现算法。
* @author
* @date 2022年11月14日11:37:20
*/
public class RandomWeight<T> {
public <T> List<T> getDataByWeight(List<T> data) throws NoSuchFieldException, IllegalAccessException {
List<T> ips = new CopyOnWriteArrayList<T>();
for (T t : data) {
Field nameField = t.getClass().getDeclaredField("name");
// setAccessible 实体中的属性是用private定义的,需要设置setAccessible 为true,才可以访问到对象
nameField.setAccessible(true);
// 获取属性值
String name =(String) nameField.get(t);
Field weightField = t.getClass().getDeclaredField("weight");
// setAccessible 实体中的属性是用private定义的,需要设置setAccessible 为true,才可以访问到对象
weightField.setAccessible(true);
// 获取属性值
Integer weight = (Integer) weightField.get(t);
// 根据权重不同,放入list 中的数量等同于权重,轮询出的的次数等同于权重
for (int ipCount =0; ipCount < weight; ipCount++) {
ips.add(t);
}
}
return ips;
}
public <T> T randomWeightRobin(List<T> data) throws NoSuchFieldException, IllegalAccessException {
List<T> ips = this.getDataByWeight(data);
// //循环随机数
// Random random=new Random();
// int index =random.nextInt();
int index = ThreadLocalRandom.current().nextInt(ips.size());
T t = ips.get(index);
return t;
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
RandomWeight<DbConfig> randomWeightRobin =new RandomWeight<DbConfig>();
List<DbConfig> dbConfigList= new ArrayList<>();
dbConfigList.add(new DbConfig("192.168.1.1", 1));
dbConfigList.add(new DbConfig("192.168.1.2", 2));
dbConfigList.add(new DbConfig("192.168.1.3", 4));
for (int i =0;i< 10 ;i++){
DbConfig server = randomWeightRobin.randomWeightRobin(dbConfigList);
System.out.println(server);
}
}
}
import com.collmall.shortlink.entity.DbConfig;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* 随机法
* 负载均衡方法随机的把负载分配到各个可用的服务器上,通过随机数生成算法选取一个服务器,
* 这种实现算法最简单,随之调用次数增大,这种算法可以达到每台服务器的请求量接近于平均。
* @author
* @date 2022年11月14日13:46:24
*/
public class Random<T> {
public <T> T randomRobin(List<T> data){
int index = ThreadLocalRandom.current().nextInt(data.size());
T t = data.get(index);
return t;
}
public static void main(String[] args) {
Random<DbConfig> randomdRobin =new Random<DbConfig>();
List<DbConfig> dbConfigList= new ArrayList<>();
dbConfigList.add(new DbConfig("192.168.1.1", 1));
dbConfigList.add(new DbConfig("192.168.1.2", 2));
dbConfigList.add(new DbConfig("192.168.1.3", 4));
for (int i=0;i< 10 ;i++){
DbConfig dbConfig = randomdRobin.randomRobin(dbConfigList);
System.out.println(dbConfig);
}
}
}
import com.collmall.shortlink.entity.DbConfig;
import java.util.ArrayList;
import java.util.List;
/**
* IP_Hash算法
* hash(ip)%N算法,通过一种散列算法把客户端来源IP根据散列取模算法将请求分配到不同的服务器上
*
* 优点:保证了相同客户端IP地址将会被哈希到同一台后端服务器,直到后端服务器列表变更。根据此特性可以在服务消费者与服务提供者之间建立有状态的session会话
*
* 缺点: 如果服务器进行了下线操作,源IP路由的服务器IP就会变成另外一台,如果服务器没有做session 共享话,会造成session丢失。
* @author
* @date 2022年11月14日14:06:41
*/
public class IpHash<T> {
/**
*
* @param data
* @param hashData
* @param
* @return
*/
public <T> T ipHashRobin(List<T> data,String hashData) {
// int hashCode = hashData.hashCode();
// int listSize = data.size();
// int index = hashCode % listSize;
int index = hashData.hashCode() % data.size();
T t = data.get(index);
return t;
}
public static void main(String[] args) {
IpHash<DbConfig> ipHash =new IpHash<DbConfig>();
List<DbConfig> dbConfigList= new ArrayList<>();
dbConfigList.add(new DbConfig("192.168.1.1", 1));
dbConfigList.add(new DbConfig("192.168.1.2", 2));
dbConfigList.add(new DbConfig("192.168.1.3", 4));
DbConfig dbConfig = ipHash.ipHashRobin(dbConfigList, "192.168.88.2");
System.out.println(dbConfig.toString());
}
}
public class DbConfig {
//id
private Long id;
//数据库名称
private String name;
//负载策略:1轮询算法 ,2 加权轮询法,3 加权随机法,4 随机法,5 IP_Hash算法
private Integer loadPolicy;
//权重: 只有 2 加权轮询法,3 加权随机法 才会用到
private Integer weight;
//是否删除:0 未删除,1是已删除
private Integer isDeleted;
//创建时间
private Date cT;
//更新时间
private Date uT;
public DbConfig(String name, Integer weight) {
this.name = name;
this.weight = weight;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getLoadPolicy() {
return loadPolicy;
}
public void setLoadPolicy(Integer loadPolicy) {
this.loadPolicy = loadPolicy;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public Integer getIsDeleted() {
return isDeleted;
}
public void setIsDeleted(Integer isDeleted) {
this.isDeleted = isDeleted;
}
public Date getCT() {
return cT;
}
public void setCT(Date cT) {
this.cT = cT;
}
public Date getUT() {
return uT;
}
public void setUT(Date uT) {
this.uT = uT;
}
/**
* 获取主键值
*
* @return 主键值
*/
@Override
protected Serializable pkVal() {
return this.id;
}
@Override
public String toString() {
return "DbConfig{" +
"id=" + id +
", name='" + name + '\'' +
", loadPolicy=" + loadPolicy +
", weight=" + weight +
", isDeleted=" + isDeleted +
", cT=" + cT +
", uT=" + uT +
'}';
}
}
参考:
Java实现5种负载均衡算法(小结)_java_脚本之家 (jb51.net)