负载均衡(Load Balance,简称 LB)是高并发、高可用系统必不可少的关键组件,目标是 尽力将网络流量平均分发到多个服务器上,以提高系统整体的响应速度和可用性。
负载均衡的主要作用如下:
大型网站都要面对庞大的用户量,高并发,海量数据等挑战。为了提升系统整体的性能,可以采用垂直扩展和水平扩展两种方式。
垂直扩展:在网站发展早期,可以从单机的角度通过增加硬件处理能力,比如 CPU 处理能力,内存容量,磁盘等方面,实现服务器处理能力的提升。但是,单机是有性能瓶颈的,一旦触及瓶颈,再想提升,付出的成本和代价会极高。这显然不能满足大型分布式系统(网站)所有应对的大流量,高并发,海量数据等挑战。
水平扩展:通过集群来分担大型网站的流量。集群中的应用服务器(节点)通常被设计成无状态,用户可以请求任何一个节点,这些节点共同分担访问压力。水平扩展有两个要点:
private static Integer pos = 0;
public String getHostByPoll(){
List<String> hosts = Host.getHostList();
String host;
synchronized (pos){
if(pos >= hosts.size()){
pos = 0;
}
host = hosts.get(pos++);
}
return host;
}
public String getHostByRandom(){
List<String> hosts = Host.getHostList();
int randomNum = new Random().nextInt(hosts.size());
System.out.println(randomNum);
return hosts.get(randomNum);
}
private static Integer pos = 0;
public String getHostByPollWeight(){
Map<String,Integer> hosts = Host.getHostMap2();
String host = null;
synchronized (pos){
for(Map.Entry<String,Integer> entry : hosts.entrySet()){
if(pos >= Host.totalWeight){
pos = 0;
}
if(pos < entry.getValue()){
host = entry.getKey();
pos++;
break;
}
}
}
return host;
}
public String getHostByRandomWeight(){
Map<String ,Integer> hosts = Host.getHostMap();
int randomNum = new Random().nextInt(Host.totalWeight);
for(Map.Entry<String,Integer> entry : hosts.entrySet()){
if(randomNum < entry.getValue()){
return entry.getKey();
}else{
randomNum -= entry.getValue();
}
}
return null;
}
public String getHostByIpHash(int ipHash) {
List<String> hosts = Host.getHostList();
int pos = ipHash % hosts.size();
return hosts.get(pos);
}
//模拟随机客户端的hash值
public int getClientHash() {
return new Random().nextInt(3);
}
public Server getServerByLeastConnect(){
List<Server> serverList = Host.getServerList();
if(serverList == null || serverList.size() == 0){
return null;
}
Server minConnectServer = serverList.get(0);
for(int i = 1; i < serverList.size();i++){
Server server = serverList.get(i);
if(minConnectServer.getConnect() > server.getConnect()){
minConnectServer = server;
}
}
minConnectServer.addConnect();
return minConnectServer;
}
其中Host源码如下:
public class Host {
private static List<String> hostList;
private static Map<String,Integer> hostMap;
private static Map<String,Integer> hostMap2;
public static int totalWeight;
static {
//初始化主机ip地址
initHostList();
initHostMap();
initHostMap2();
}
public static void initHostList(){
hostList = new ArrayList<>();
hostList.add("192.168.0.1");
hostList.add("192.168.0.2");
hostList.add("192.168.0.3");
}
public static void initHostMap(){
hostMap = new HashMap<>();
//这里为了方便用A、B、C代表三个主机ip
hostMap.put("A",5);
hostMap.put("B",2);
hostMap.put("C",3);
Map<String ,Integer> hosts = Host.getHostMap();
for(int v : hosts.values()){
totalWeight += v;
}
}
public static void initHostMap2(){
hostMap2 = new HashMap<>();
int weight = 0;
for(Map.Entry<String,Integer> entry : hostMap.entrySet()){
weight += entry.getValue();
hostMap2.put(entry.getKey(),weight);
}
}
public static List<String> getHostList(){
return hostList;
}
public static Map<String,Integer> getHostMap(){
return hostMap;
}
public static Map<String,Integer> getHostMap2(){
return hostMap2;
}
}
文章所有源码地址都放到了Github上了,有兴趣的小伙伴可以下载下来看看哦。
GitHub源码地址:git@github.com:HelloWorld19930603/alien_cat.git
该算法源码对应目录:alien_cat/algorithm/src/main/java/com/aliencat/algorithm/lb