package com.hengyu.ticket.test;
import java.math.BigInteger;
import java.util.*;
/**
* Created by lgf on 2016/4/3.
* java 实现负载均衡算法
*/
public class LoadBalancing {
private final static String SERVER_MASTER = "master" ;
private final static String SERVER_SLAVE = "slave" ;
//上一次,选择服务器的编号
private static Integer currentIndex = -1;
//当前权重
private static Integer currentWeight = 0;
//最大权重
private static Integer maxWeight = 0;
//最大权重公约数
private static Integer gcdWeight = 0;
//主服务器
private static Server master;
//服务器集合
private static Map servers = Collections.synchronizedMap(new HashMap());
public static Integer getCurrentIndex() {
return currentIndex;
}
public static Integer getCurrentWeight() {
return currentWeight;
}
public static Integer getMaxWeight() {
return maxWeight;
}
public static Server getMaster() {
return master;
}
public static void setMaster(Server master) {
LoadBalancing.master = master;
}
public static Integer getGcdWeight() {
return gcdWeight;
}
//添加服务器
public static void addServer(Server server){
if(server==null){
throw new RuntimeException("error:server is nullable!");
}
int index = servers.size();
servers.put(String.valueOf(index),server);
if(server.getType()!=null&&SERVER_MASTER.equals(server.getType())){
servers.put(SERVER_MASTER,server);
}else if(server.getType()==null){
server.setType(SERVER_SLAVE);
}
}
//添加服务器
public static void addServer(List servers) {
for (int i = 0; i < servers.size(); i++) {
Server server = servers.get(i);
addServer(server);
}
LoadBalancing.initOrReload();
}
//查找权重,计算最大权重公约数
public synchronized static void initOrReload(){
Set keys = servers.keySet();
Server prev_server = null ;
for(String key:keys){
Server server = servers.get(key);
if(prev_server!=null){
gcdWeight = new BigInteger(String.valueOf(prev_server.getWeight())).gcd(new BigInteger(String.valueOf(prev_server.getWeight()))).intValue();
}
if(server.getWeight()>maxWeight){
maxWeight = server.getWeight();
}
prev_server = server;
}
if(master==null){
master = servers.get("0");
master.setType(SERVER_MASTER);
servers.put(SERVER_MASTER,master);
}
}
//轮询服务器
public static Server getServer(){
int count = 0;
int size = servers.size();
while (true){
currentIndex = (currentIndex+1)%size;
if(currentIndex==0){
currentWeight = currentWeight - gcdWeight;
if (currentWeight <= 0) {
currentWeight = maxWeight;
}
}
Server server = servers.get(String.valueOf(currentIndex));
if(server!=null&&server.getWeight()>=currentWeight&&!server.isDown){
server.addAccessCount();
return server;
}
if(count>=size){
if(master.isDown){
new RuntimeException("error:master is down!");
}
return master;
}
count++;
}
}
public static Map getServers() {
return servers;
}
public static class Server {
//服务器编号
private String id;
///服务器ip
private String ip;
//权重
private int weight;
//类型,主从
private String type;
//访问数量
private Integer accessCount = 0;
//是否脱机
private boolean isDown;
public Server(String ip, int weight) {
this.ip = ip;
this.weight = weight;
}
public int getAccessCount() {
return accessCount;
}
public void setAccessCount(int accessCount) {
this.accessCount = accessCount;
}
public void addAccessCount() {
synchronized (this.accessCount){
this.accessCount++;
}
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public boolean isDown() {
return isDown;
}
public void setDown(boolean down) {
if((this.isDown&&down)||(!this.isDown&&!down)){
return;
}else{
//移除或恢复操作
initOrReload();
}
isDown = down;
}
}
}
package com.hengyu.ticket;
import com.hengyu.ticket.test.LoadBalancing;
import com.hengyu.ticket.test.ServerNode;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) throws InterruptedException {
LoadBalancing.Server s = new LoadBalancing.Server("192.168.0.0.5",3);
LoadBalancing.addServer(Arrays.asList(
new LoadBalancing.Server("192.168.0.0.1",3),
new LoadBalancing.Server("192.168.0.0.2",50)
,new LoadBalancing.Server("192.168.0.0.3",3),
new LoadBalancing.Server("192.168.0.0.4",3),
s
)
);
long currtime = System.currentTimeMillis();
for (int i = 0; i < 15; i++) {
if(i>=2){
LoadBalancing.getMaster().setDown(true);
}
Thread t = new Thread(new Runnable() {
@Override
public void run() {
LoadBalancing.Server server = LoadBalancing.getServer();
System.out.println("ip:"+server.getIp()+" weight:" + server.getWeight());
}
});
t.start();
t.join();
}
currtime = System.currentTimeMillis() - currtime;
System.out.println("time ====> " + currtime/1000);
Map servers = LoadBalancing.getServers();
for (String key:servers.keySet()){
LoadBalancing.Server server = servers.get(key);
System.out.println(server.getType()+" "+"ip:"+server.getIp()+" weight:" + server.getWeight() +" accesscount:"+server.getAccessCount()
+" isdown:" + server.isDown());
}
System.out.println(LoadBalancing.getGcdWeight());
System.out.println(LoadBalancing.getMaxWeight());
}
}